PowerCMS™
2025年1月1日購入分よりライセンスの価格を改定いたします。
[ブログ] PowerCMS 6 でのアップデートまとめ を追加しました。
[ブログ] PowerCMS サポートの実績 (2024年10月) を追加しました。
[よくあるご質問] スマートフォンでは使えない機能がありますか? を追加しました。

PowerCMS ブログ

ホーム > PowerCMS ブログ > PowerCMS 3 > ContactFormのフォーム項目(設問のフォーマット)をプラグインで追加する

2012年09月24日

ContactFormのフォーム項目(設問のフォーマット)をプラグインで追加する

PowerCMS 3のコンタクトフォーム(ContactForm.pack)では、ノンプログラミング、管理画面の設定だけで簡単にフォームが作成できます。設問の形式はテキスト、複数行テキスト、ラジオボタンやチェックボックス、日付、メールアドレスなどが予め用意されていますが、プラグインによってこの項目を任意に追加できるようになっています。この、フォーム項目を追加するプラグインの作成方法について解説します。

PowerCMSの「日付」型のフォーム項目はデフォルトはカレンダーから日付を選択するようになっていますが(初期状態では今日の日付が選択されています)、例えば生年月日を入力させるようなケースではこの形式は不向きです。そこで、ドロップダウン形式で年月日を選択するようなフォーム項目を利用できるようにプラグインを作成します。

※サンプルプラグインの CFDateDropDownField は PowerCMS 4.02 以降に同梱されています。

デフォルトの日付フォーム項目

プラグインで拡張した日付フォーム項目

ファイル構成

$MT_DIR/
|__ plugins/
   |__ CFDateDropDownField/
      |__ config.yaml
      |__ lib/
      |  |__ CFDateDropDownField
      |     |__Plugin.pm
      |     |__L10N.pm
      |     |__L10N
      |        |__ja.pm
      |__ template/
         |__ date_dropdown.mtml

レジストリへの登録

まず、config.yamlもしくは.plのプラグインで registry に contactform_objects を登録します。date_dropdown はフォーム項目のIDで、他の項目と重複しない値である必要があります。

contactform_objects:
    date_dropdown:
        order: 1100
        name: Date(Multiple dropdown format)
        template_type: date_dropdown
        validate: $cfdatedropdownfield::CFDateDropDownField::Plugin::_validate_date_dropdown
        format: $cfdatedropdownfield::CFDateDropDownField::Plugin::_format_date_dropdown

オプションは以下の通りです。

  • order : フォーム項目を作成する画面でのドロップダウン内の表示順
  • name : ドロップダウンのラベル(自動的に言語ファイルの値が適用されます)
  • template_type : デフォルトのテンプレート(この場合plugins/Plugin名/template_type/date_dropdown.mtml の中身が使われます。拡張子はmtmlとなります)。
  • validate : このメソッドが0を返すと入力チェックによりエラーになります。このプラグインでは2月31日など、存在しない日付が渡った時にエラーを返すようなコードを入れています。
  • format : 最終的にDBへ格納する値や確認画面で入力値を加工するコードが必要なな場合に指定します。今回は、年・月・日をつなげた形にする必要があるため、formatでコードを書く必要があります。

validate 及び format の処理は以下のようなものです。

sub _format_date_dropdown {
    my ( $app, $contactform ) = @_;
    my $basename = $contactform->basename;
    my $hidden = $app->param( $basename );
    if ( $hidden ) { # 確認画面を経てポストされた時
        if ( PowerCMS::Util::valid_ts( $hidden ) ) { # 日付が正しいかどうか
            return $hidden;
        } else {
            $app->param( $basename, undef );
        }
    }
    my $year = $app->param( $basename . '-year' );
    my $month = $app->param( $basename . '-month' );
    my $day = $app->param( $basename . '-day' );
    if ( $month && $month =~ /^[0-9]{1}$/ ) {
        $month = '0' . $month;
    }
    if ( $day && $day =~ /^[0-9]{1}$/ ) {
        $month = '0' . $month;
    }
    if ( ( $year =~ /^[0-9]{4}$/ ) && ( $month =~ /^[0-9]{2}$/ ) && ( $day =~ /^[0-9]{2}$/ ) ) { # 年月日を連結する
        my $ts = $year . $month . $day . '000000'; 
        return $ts;
    }
    return '';
}

sub _validate_date_dropdown {
    if ( my $ts = _format_date_dropdown( @_ ) ) {
        if ( PowerCMS::Util::valid_ts( $ts ) ) {
            return 1; # 正しいタイムスタンプの場合に1を返す
        }
    }
    return 0;
}

コールバック

同じくconfig.yamlもしくは.plのプラグインでコールバック処理を定義することができます。

callbacks:
    template_param.edit_contactform: $cfdatedropdownfield::CFDateDropDownField::Plugin::_cb_tp_edit_contactform
    contactform.pre_build.date_dropdown: $cfdatedropdownfield::CFDateDropDownField::Plugin::_cb_contactform_pre_build_date_dropdown
  • template_param.edit_contactform : フォーム項目の作成、編集画面のパラメタの追加

パラメタ js_include に追記することで、ドロップダウンから「日付(ドロップダウン)」を選択した時のJavaScript処理を追加できます。

sub _cb_tp_edit_contactform {
    my ( $cb, $app, $param, $tmpl ) = @_;
    $param->{ js_include } .= <<'EOF';
<script type="text/javascript">
(function(j) {
  var typeOfDateDropDown = {
    date_dropdown: {
      visibility: {
        opt: true,
        size: false,
        def: true,
        validate: true,
        length: false
      },
    }
  };
  j.contactForm.addType(typeOfDateDropDown);
})(jQuery);
</script>
EOF
}

visibilityは「日付(ドロップダウン)」を選択した時にどのフィールドを表示/非表示にするかを指定するものです。

  • opt : 「オプション」欄を表示する
  • size : 表示数(複数選択ドロップダウンの時、「表示数」欄)を表示する
  • def : 「既定値」欄を表示する
  • validate : 「入力チェックを行う」欄を表示する
  • contactform.pre_build.date_dropdown : フォーム項目のテンプレートをビルドする直前にパラメタを設定したり、テンプレートに手を加えることができます。
sub _cb_contactform_pre_build_date_dropdown {
    my ( $cb, $app, $mtml, $args, $params ) = @_;
    my $ctx = $args->{ ctx };
    my $contactform = $ctx->stash( 'contactform' );
    my $basename = $contactform->basename;
    my $default = build_tmpl( $app, $contactform->default, $args, $params );
    if ( $default ) {
        $default =~ s/,//g;
    }
    my ( $default_year, $default_month, $default_day );
    my $set_default;
    if ( ref( $app ) eq 'MT::App::ContactForm' ) {
        if ( $app->mode eq 'confirm' ) {
            $default_year = $app->param( $basename . '-year' );
            $default_month = $app->param( $basename . '-month' );
            $default_day = $app->param( $basename . '-day' );
            $set_default = 1;
            if ( $app->param( $basename ) eq '1' ) {
                if (! _format_date_dropdown( $app, $contactform ) ) {
                    $params->{ field_error } = 'required';
                }
            }
        }
    }
    if (! $set_default ) {
        if ( $default ) {
            $default_year = substr( $default, 0, 4 );
            $default_month = substr( $default, 4, 2 );
            $default_day = substr( $default, 6, 2 );
        }
    }
    my @field_loop_year;
    my @field_loop_month;
    my @field_loop_day;
    push ( @field_loop_year, { 'option_value' => '' } );
    push ( @field_loop_month, { 'option_value' => '' } );
    push ( @field_loop_day, { 'option_value' => '' } );
    for ( 1 .. 12 ) {
        my $month = sprintf( "%02d", $_ );
        push ( @field_loop_month, { 'option_value' => $month,
                                    'option_default' => ( $month == $default_month ) } );
    }
    for ( 1 .. 31 ) {
        my $day = sprintf( "%02d", $_ );
        push ( @field_loop_day, { 'option_value' => $day,
                                  'option_default' => ( $day == $default_day ) } );
    }
    my $options = build_tmpl( $app, $contactform->options, $args, $params );
    my @years = split( /,/, $options );
    if ( ( scalar @years ) == 2 ) {
        for ( $years[ 0 ] .. $years[ 1 ] ) {
            push ( @field_loop_year, { 'option_value' => $_,
                                       'option_default' => ( $_ == $default_year ) } );
        }
    } else {
        for my $year( @years ) {
            push ( @field_loop_year, { 'option_value' => $year,
                                       'option_default' => ( $year == $default_year ) } );
        }
    }
    $params->{ 'field_loop-year' } = \@field_loop_year; # 年
    $params->{ 'field_loop-month' } = \@field_loop_month; # 月
    $params->{ 'field_loop-day' } = \@field_loop_day; # 日
}

デフォルトテンプレート

デフォルトテンプレートは、フォーム項目を最初に保存した時に自動的に生成されるフォーム項目のテンプレートです。プラグインのディレクトリ配下の template ディレクトリ配下に registryに指定したID+拡張子mtmlという名前で作成します。

<mt:SetVarTemplate name="DropdownDate">
        <ul class="form-element">
            <li><select name="<mt:var name="field_basename">-year" id="<mt:var name="field_basename">-year">
                <mt:loop name="field_loop-year">
                <option<mt:if name="option_default"> selected="selected"</mt:if> value="<mt:var name="option_value" escape="html">">
                <mt:if name="option_value"><mt:var name="option_value" escape="html"><mt:else><MTTrans component="CFDateDropDownField" phrase="Select..."></mt:else></mt:if></option>
                </mt:loop>
            </select>
            </li>
            <li><select name="<mt:var name="field_basename">-month" id="<mt:var name="field_basename">-month">
                <mt:loop name="field_loop-month">
                <option<mt:if name="option_default"> selected="selected"</mt:if> value="<mt:var name="option_value" escape="html">">
                <mt:if name="option_value"><mt:var name="option_value" escape="html"><mt:else><MTTrans component="CFDateDropDownField" phrase="Select..."></mt:else></mt:if></option>
                </mt:loop>
            </select></li>
            <li><select name="<mt:var name="field_basename">-day" id="<mt:var name="field_basename">-day">
                <mt:loop name="field_loop-day">
                <option<mt:if name="option_default"> selected="selected"</mt:if> value="<mt:var name="option_value" escape="html">">
                <mt:if name="option_value"><mt:var name="option_value" escape="html"><mt:else><MTTrans component="CFDateDropDownField" phrase="Select..."></mt:else></mt:if></option>
                </mt:loop>
            </select></li>
        </ul>
        <input type="hidden" name="<mt:var name="field_basename">" value="1" />
</mt:SetVarTemplate>
<$mt:SetVar name="display_description" value="0"$>
<mt:unless name="field_mode"><$mt:SetVar name="display_description" value="1"$></mt:unless>
<mt:if name="field_error"><$mt:SetVar name="display_description" value="1"$></mt:if>
<div id="<mt:var name="field_basename">-field" class="contact-form-field clf">
    <p class="form-label">
        <label for="<mt:var name="field_basename">">
        <mt:var name="field_name" escape="html">
        <mt:if name="display_description">
            <mt:if name="field_description"><span class="description"><mt:var name="field_description"></span></mt:if>
            <mt:if name="field_required"><span class="must"><$MT:Trans phrase="*Required" component="ContactForm"$></span></mt:if>
        </mt:if>
        </label>
    </p>
    <mt:if name="field_mode">
        <mt:if name="field_error">
            <div class="form-element">
                <mt:GetVar name="DropdownDate">
                <p class="field_error">
                <mt:if name="field_error" eq="invalid">
                    <$MT:Trans phrase="Invalid '[_1]'." component="ContactForm" params="$field_name"$>
                <mt:else>
                    <$MT:Trans phrase="'[_1]' is required." component="ContactForm" params="$field_name"$>
                </mt:else>
                </mt:if>
                </p>
            </div>
        <mt:else>
        <p class="form-element">
            <span class="field_value">
                <mt:var name="field_value" format_ts="%Y-%m-%d">
                <input type="hidden" name="<mt:var name="field_basename">" value="<mt:var name="field_value" escape="html">" />
            </span>
        </p>
        </mt:else>
        </mt:if>
    <mt:else>
    <mt:GetVar name="DropdownDate">
    </mt:else>
    </mt:if>
</div>

カテゴリー
PowerCMS 3
プラグイン
技術情報

Recent Entries