Как использовать файл шаблона для оформления формы?

50

В то время как узлы, комментарии, блоки и многое другое в Drupal тематизируются с использованием файлов шаблонов тем (например, node.tpl.php), формы - это отдельная история. Для форм нет файлов шаблонов тем. Как получить конкретную форму для использования собственного шаблона темы?

Chaulky
источник

Ответы:

73

Вполне разумно использовать файл tpl для отображения формы. Вы можете использовать множество посторонних CSS и #prefix/ #suffixproperties для достижения аналогичных результатов, но при использовании 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 / шаблон / форма / 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
Вы правы, я добавил это.
Чарли Шлиссер
5
Очень важным примечанием является то, что в нижней части фрагмента кода находится print drupal_render_children($form)форма, которая действительно делает вещи :).
Крис Роквелл
Хороший ответ. Я могу добавить, что вам нужно указать дополнительно engine, если вы используете что-то не по умолчанию. Например 'engine' => 'twig'.
Милковский
1
Хороший ответ. Имейте в виду, если вы хотите создать тему формы администратора, например user_profile_formили user_register_form. В этом сценарии вам нужно либо: а) выполнить тематику в теме администратора (или ее подтему, если вы не можете изменить базовую тему администратора), либо б) поместить тематику в пользовательский модуль. В противном случае ваши темы не будут видны.
therobyouknow
18

Вы должны реализовать hook_form_alter () в модуле или template.php и установить свойство формы #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) ?> 
mrded
источник
1
#themeСвойство так очень просто и упоминается в первый раз действительно низко в ответах, супер странно. Это определенно мой любимый метод.
Мэтт Флетчер
1
Я проверил этот код, и он работает, как ожидалось.
Влад Савицкий,
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, который имеет встроенный стиль, чтобы сделать фоновый цвет красным. Он также добавляет абзац справочного текста в начало формы.

Вот как выглядит моя форма входа в систему пользователя после загрузки приведенного выше кода:

Индивидуальная форма входа

См. Ссылку API формы для получения дополнительной информации: Ссылка API формы

Camsoft
источник
1
Просто для пояснения использования встроенных стилей в этом примере просто для упрощения примера. Я не рекомендую использовать встроенные стили, и вы должны использовать классы.
Camsoft
Я не поддерживаю использование файла шаблона для визуализации формы; на самом деле, я также сказал, что я никогда не использовал файл шаблона для визуализации формы (я фактически изменил код модуля, который использовал файл шаблона для формы), и что Drupal не использует шаблон файлы для визуализации форм.
kiamlaluno
5
Что делать, если вы хотите радикально изменить разметку? Иногда файл шаблона является лучшим вариантом.
Коссович
6
Разметка в виде логики построителя пахнет.
Чарли Шлиссер
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().

киамлалуно
источник
Как мне предложить форму, определенную некоторыми другими модулями, возможно, основными модулями, чтобы использовать мою функцию / шаблон темы?
Шафиул
Set $form['#theme'].
kiamlaluno
1
Не работает, когда я отправляю форму, она не переходит к функции
form_submit
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

Если то, что вам нужно для стиля, не имеет идентификатора или достаточно точного селектора, тогда необходимо использовать hookподход, чтобы изменить HTML и добавить идентификаторы.

IMO, использующий встроенный стиль для элементов, является очень плохой практикой, которая должна быть устарела и заменена использованием classиid

Ричард Харрисон
источник
0

Чтобы оформить тему формы, вы можете использовать пользовательский CSS, как описано в Themeing Drupal 7 Forms (включая CSS и JS) .

В основном вам нужно выполнить эти шаги:

  1. Зарегистрируйте путь к форме, используя hook_menu ()
  2. Определите форму
  3. Зарегистрируйте функцию темы с hook_theme ()
  4. Напишите функцию темы
  5. Создайте файлы CSS и JavaScript
Шаси Кант
источник
-2

Я уверен, что вы можете использовать шаблон для форм, но вы должны использовать hook_theme, чтобы сначала зарегистрировать шаблон. У меня была ситуация, когда форма действительно должна была быть основана на таблице, а не на div, и простые изменения #prefix и #suffix на самом деле не обрезали ее. Если интересно, я мог бы попытаться выкопать пример.

Malks
источник