如何使用模板文件为表单添加主题?


50

虽然Drupal中的节点,注释,块和许多其他内容使用主题模板文件(例如node.tpl.php)来主题化,但表单却是另一回事。没有用于表单的主题模板文件。如何获得特定的表单以使用自定义主题模板?

Answers:


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 2014年

您是对的,我已经添加了。
查理·施利瑟

5
非常重要的一点是,在代码片段的底部,print drupal_render_children($form)这使得表单实际上可以完成工作:)。
克里斯·罗克韦尔

好答案。我可以补充一点engine,如果您使用的不是默认值,则需要另外指定。例如'engine' => 'twig'
milkovsky '16

1
好答案。如果要设置诸如user_profile_form或的管理表单的主题,请记住user_register_form。在这种情况下,您将需要a)在admin主题中进行主题化(如果无法更改基本admin主题,则以其为子主题)或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',
    ),
  );
}

然后添加带有以下代码的form--user_login.tpl.php模板以呈现表单:

<?php print drupal_render_children($form) ?> 

1
#theme属性是如此简单,并且在答案中第一次提到了它,这太奇怪了。这绝对是我最喜欢的方法。
马特·弗莱彻

1
我测试了此代码,它可以按预期工作。
VladSavitsky

14

即使您可能可以使用kiamlaluno的解决方案,但我个人不会。

您需要表单的模板文件的原因是什么?如果是因为您希望现有表单的标记稍有不同,该怎么办?如果是这样,则可以hook_form_alter()在呈现表单之前先对其进行修改。使用Form 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参考:Form API参考


1
仅在本示例中阐明内联样式的使用只是为了简化示例。我不建议使用内联样式,而应该使用类。
Camsoft 2011年

我不支持使用模板文件来呈现表单。实际上,我还说过我从未使用过模板文件来呈现表单(我实际上已经更改了将模板文件用于表单的模块的代码),而Drupal不使用模板文件以呈现表单。
kiamlaluno

5
如果您想从根本上更改标记怎么办?有时,模板文件是更好的选择。
cossovich 2013年

6
表单逻辑生成器中的标记有异味。
Charlie Schliesser 2014年

1
尽管此解决方案在大多数情况下都有效,但是在Ajax回调中刷新表单呈现时,它实际上可能会中断
PatrickS 2015年

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()


我如何建议其他模块(可能是核心模块)定义的形式使用主题功能/模板?
Shafiul 2012年

设置$form['#theme']
kiamlaluno

1
不起作用,当我提交表单时,它将不会进入form_submit函数
gbstack 2014年

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在使用内联元素风格是一个非常不好的做法,应该被淘汰,并通过使用替代classid



-2

我很确定您能够使用表单模板,但是首先必须使用hook_theme来注册模板。我遇到的一种情况是,表单实际上确实需要基于表而不是基于div,并且简单的#prefix和#suffix更改并没有真正实现。如果有兴趣,我可能会尝试找出一个例子。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.