テンプレートファイルを使用してフォームのテーマを設定する方法は?


50

Drupalのノード、コメント、ブロック、その他多くのものはテーマテンプレートファイル(node.tpl.phpなど)を使用してテーマ化されていますが、フォームは異なるストーリーです。フォーム用のテーマテンプレートファイルはありません。カスタムテーマテンプレートを使用する特定のフォームを取得するにはどうすればよいですか?

回答:


73

tplファイルを使用してフォームを表示することは完全に合理的です。多くの無関係なCSSおよび#prefix/ #suffixプロパティを使用して同様の結果を得ることができますが、tplを使用することで、ロジックとプレゼンテーションレイヤーの分離を乱雑にする必要がなく、のようないCSSセレクターをターゲットにする必要がありません#user-login label。Drupal 7の例を次に示します...

mytheme / template.php:

function mytheme_theme($existing, $type, $theme, $path) {
    // Ex 1: the "story" node edit form.
    $items['story_node_form'] = array(
        'render element' => 'form',
        'template' => 'node-edit--story',
        'path' => drupal_get_path('theme', 'mytheme') . '/template/form',
    );

    // Ex 2: a custom form that comes from a custom module's "custom_donate_form()" function.
    $items['custom_donate_form'] = array(
        'render element' => 'form',
        'template' => 'donate',
        'path' => drupal_get_path('theme', 'mytheme') . '/template/form',
    );

    return $items;
}

custom_donate_form():

function custom_donate_form($form, &$form_state) {
    $form['first_name'] = array(
        '#type' => 'textfield',
        '#attributes' => array('placeholder' => t('First name')),
    );
    $form['last_name'] = array(
        '#type' => 'textfield',
        '#attributes' => array('placeholder' => t('Last name')),
    );
    $form['address'] = array(
        '#type' => 'textfield',
        '#attributes' => array('placeholder' => t('Address')),
    );
    $form['city'] = array(
        '#type' => 'textfield',
        '#attributes' => array('placeholder' => t('City')),
    );
    $form['state'] = array(
        '#type' => 'select',
        '#options' => array(
            'default' => 'State',
            '...' => '...',
        ),
    );
    $form['zip'] = array(
        '#type' => 'textfield',
        '#attributes' => array('placeholder' => t('Zip')),
    );
    $form['email'] = array(
        '#type' => 'textfield',
        '#attributes' => array('placeholder' => t('Email')),
    );
    $form['phone'] = array(
        '#type' => 'textfield',
        '#attributes' => array('placeholder' => t('Phone')),
    );
    $form['submit'] = array(
        '#type' => 'submit',
        '#value' => 'Submit',
    );

    return $form;
}

mytheme / template / form / donate.tpl.php:

<div class="row">
    <div class="small-12 medium-12 large-8 columns">

        <div class="row">
            <div class="small-12 columns">
                <h5>Contact Information</h5>
            </div>
        </div>

        <div class="row">
            <div class="small-12 large-6 medium-6 columns">
                <?php print render($form['first_name']); ?>
            </div>
            <div class="small-12 large-6 medium-6 columns">
                <?php print render($form['last_name']); ?>
            </div>
        </div>

        <div class="row">
            <div class="small-12 medium-6 large-6 columns">
                <?php print render($form['address']); ?>
            </div>

            <div class="small-12 medium-6 large-6 columns">
                <?php print render($form['city']); ?>
            </div>
        </div>

        <div class="row">
            <div class="small-12 medium-3 large-3 columns">
                <?php print render($form['state']); ?>
            </div>

            <div class="small-12 medium-3 large-3 columns">
                <?php print render($form['zip']); ?>
            </div>

            <div class="medium-6 large-6 columns"></div>
        </div>

        <div class="row">
            <div class="small-12 medium-6 large-6 columns">
                <?php print render($form['email']); ?>
            </div>

            <div class="small-12 medium-6 large-6 columns">
                <?php print render($form['phone']); ?>
            </div>
        </div>
    </div>

    <div class="row">
        <div class="small-12 medium-12 large-8 large-offset-2 columns">
            <?php print render($form['submit']); ?>
        </div>
    </div>
</div>

<!-- Render any remaining elements, such as hidden inputs (token, form_id, etc). -->
<?php print drupal_render_children($form); ?>

これはFoundationを使用しており、次のようなフォームを提供します。

ここに画像の説明を入力してください


mytheme_theme()関数で戻り状態を忘れたようです
sel_space 14年

あなたは正しい、私はそれを追加しました。
チャーリーシュリーサー14年

5
非常に重要な注意点は、コードスニペットの下部にあるprint drupal_render_children($form)、フォームが実際に何かをするようにすることです:)。
クリスロックウェル

いい答えだ。engineデフォルト以外のものを使用している場合、追加で指定する必要があることを追加できます。例'engine' => 'twig'
ミルコフスキー

1
素敵な答え。user_profile_formまたはなどの管理フォームをテーマにする場合は、注意してくださいuser_register_form。このシナリオでは、a)管理テーマでテーマを実行する(または、ベース管理テーマを変更できない場合はサブテーマをサブテーマにする)か、b)テーマをカスタムモジュールに配置する必要があります。そうしないと、テーマが表示されません。
therobyouknow

18

モジュールまたはtemplate.phpにhook_form_alter()を実装し、フォームの#themeプロパティを設定する必要があります。

/**
 * Implements hook_form_alter().
 */
function hook_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'user_login') {
    $form['#theme'] = array('overwrite_user_login');
  }
}

次に、新しいテーマを実装します。

/**
 * Implements hook_theme().
 */
function hook_theme($existing, $type, $theme, $path){
  return array(
    'overwrite_user_login' => array(
      'render element' => 'form',
      'template' => 'form--user_login',
      'path' => $path . '/templates',
    ),
  );
}

そして、フォームを追加します--user_login.tpl.phpテンプレートを次のコードでフォームをレンダリングします:

<?php print drupal_render_children($form) ?> 

1
#themeプロパティは、スーパー奇妙なので、非常にシンプルであると回答の中で初めて、本当に低ダウンのために言及されています。これは間違いなく私のお気に入りの方法です。
マットフレッチャー

1
このコードをテストしましたが、期待どおりに機能します。
VladSavitsky

14

kiamlalunoのソリューションを使用できるかもしれませんが、個人的にはそうしません。

フォームのテンプレートファイルが必要な理由は何ですか?既存のフォームにわずかに異なるマークアップが必要な場合ですか?その場合hook_form_alter()は、レンダリング前にフォームを変更するために使用できます。フォームAPIを使用すると、すべてのフォームフィールドを変更してHTML要素などを挿入できます。

以下は、hook_form_alter()標準のdrupalログインフォームブロックを変更するために作成した例です。

/**
 * Implements hook_form_alter().
 */
function MYMODULE_form_alter(&$form, &$form_state, $form_id) {

  switch ($form_id) {
    case 'user_login_block':

      // Form modification code goes here.
            $form['divstart'] = array(
                '#value' => '<div style="background-color: red;">',
                '#weight' => -1,
            );

            $form['instruct'] = array(
                '#value' => '<p>Enter your username and password to login</p>',
                '#weight' => 0,
            );          

            $form['divend'] = array(
                '#value' => '</div>',
                '#weight' => 4,             
            );
      break;
  }
}

上記の例は、フォーム全体をDIV内にラップします。DIVは、背景色を赤に変えるインラインスタイルを持っています。また、ヘルプテキストの段落をフォームの先頭に追加します。

上記のコードがロードされると、これは私のユーザーログインフォームのようになります。

カスタマイズされたログインフォーム

詳細については、Form APIリファレンスをご覧ください。FormAPIリファレンス


1
この例でインラインスタイルの使用を明確にすることは、例を単純化することです。インラインスタイルの使用はお勧めしません。クラスを使用する必要があります。
カムソフト

フォームのレンダリングにテンプレートファイルを使用することはサポートしていません。実際のところ、テンプレートファイルを使用してフォームをレンダリングしたことはなく(フォームにテンプレートファイルを使用していたモジュールのコードを実際に変更した)、Drupalはテンプレートを使用していないとも言いました。フォームをレンダリングするファイル。
キアムルノ

5
マークアップを根本的に変更したい場合はどうしますか?場合によっては、テンプレートファイルの方が良いオプションです。
cossovich

6
フォームロジックビルダーのマークアップは臭いがします。
チャーリーシュリーサー14年

1
このソリューションはほとんどの場合に機能しますが、フォームレンダリングがajaxコールバックで更新されると実際に破損する可能性があります
-PatrickS

13

実際、フォームにテンプレートファイルを使用する必要はありません。
私が見る限り、フォームまたはフォームの一部を特定の方法でレンダリングする必要がある場合、Drupalコアコードはテーマ関数を使用します。drupal_render()を呼び出すテーマ関数は通常、あらゆる目的に十分です。

質問に回答するために、フォーム用のテンプレートファイルを作成することは、フォーム用ではないテンプレートファイルを作成することと同じです。

テーマ関数として、フォームビルダーコールバックの名前を使用して、テーマ関数を定義します。コードは次のようになります。

/**
 * Implementation of hook_theme().
 */

 function mymodule_theme() {
   return array(
     'mymodule_form' => array(
       'template' => 'mymodule-form',
       'file' => 'mymodule.admin.inc',
       'arguments' => array('form' => NULL),
     ),
   );
 }

フォームに値が含まれている場合$form['field_1']、その値はテンプレートファイルでとして使用できます$field_1。テンプレートファイルは、から渡されtemplate_preprocess_mymodule_form()た値を使用することもできます。


テーマ機能/テンプレートを使用するために、他のモジュール、おそらくコアモジュールで定義されたフォームを提案するにはどうすればよいですか?
シャフィウル

設定し$form['#theme']ます。
キアマルーノ

1
私は、フォームを送信したときに動作していない、それはform_submit機能に行くことはありません
gbstack

1

セレクターを使用してCSSファイルに追加することで常にスタイルを設定し、コアログインフォームに対して次のようにスタイルを設定する要素を識別します。

#user-login
{
   border:1px solid #888;
   padding-left:10px;
   padding-right:10px;
   background-image: url(http://www.zaretto.com/images/zlogo_s.png);
   background-repeat:no-repeat;
   background-position:right;
}

#user-login label
{
    display: inline-block;
}

上記に単純に追加する sites/all/themes/theme-name/css/theme-name.css

スタイル設定に必要なものにIDまたは十分に正確なセレクターがない場合は、hookアプローチを使用してHTMLを変更し、識別子を追加する必要があります。

要素でインラインスタイルを使用するIMOは非常に悪い習慣であり、非推奨でclassあり、id


0

フォームのテーマを設定するには、テーマのDrupal 7フォーム(CSSとJSを含む)で説明されているように、カスタムcssを使用できます。

基本的に、次の手順を実行する必要があります。

  1. hook_menu()を使用してフォームへのパスを登録します
  2. フォームを定義する
  3. hook_theme()でテーマ関数を登録します
  4. テーマ関数を書く
  5. CSSおよびJavaScriptファイルを作成する

-2

フォームにテンプレートを使用できると確信していますが、そもそもhook_themeを使用してテンプレートを登録する必要があります。フォーム divベースではなくテーブルベースである必要があり、単純な#prefixと#suffixの変更では実際にはカットされない状況がありました。興味があれば、おそらく例を試してみてください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.