Jak użyć pliku szablonu do stworzenia formularza?


50

Podczas gdy węzły, komentarze, bloki i wiele innych rzeczy w Drupal są tematyczne przy użyciu plików szablonów motywów (takich jak node.tpl.php), formy są inną historią. Brak plików szablonów motywów dla formularzy. Jak uzyskać konkretny formularz do korzystania z niestandardowego szablonu motywu?

Odpowiedzi:


73

Całkowicie uzasadnione jest użycie pliku tpl do wyświetlenia formularza. Możesz użyć wielu obcych CSS i #prefix/ #suffixwłaściwości, aby osiągnąć podobne wyniki, ale używając tpl, nie musisz zaśmiecać separacji warstw logiki i prezentacji i nie musisz celować w brzydkie selektory CSS, takie jak #user-login label. Oto przykład w 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); ?>

To używa Fundacji , która daje nam taki formularz:

wprowadź opis zdjęcia tutaj


wygląda na to, że zapomniałeś stanu zwrotnego funkcji mytheme_theme ()
sel_space

Masz rację, dodałem to.
Charlie Schliesser

5
Bardzo ważna uwaga jest taka, że ​​na dole fragmentu kodu jest to, print drupal_render_children($form)co sprawia, że ​​formularz robi rzeczy :)
Chris Rockwell,

Dobra odpowiedź. Mogę dodać, że musisz dodatkowo określić engine, jeśli używasz czegoś innego niż domyślny. Np 'engine' => 'twig'.
milkovsky

1
Niezła odpowiedź. Pamiętaj, jeśli chcesz utworzyć motyw formularza administracyjnego, takiego jak user_profile_formlub user_register_form. W tym scenariuszu musisz albo: a) wykonać temat w motywie administratora (lub wyłączyć go, jeśli nie możesz zmienić podstawowego motywu administratora) lub b) umieścić motyw w niestandardowym module. W przeciwnym razie Twoje motywy nie będą widoczne.
therobyouknow

18

Musisz zaimplementować hook_form_alter () w module lub template.php i ustawić właściwość #theme formularza :

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

Następnie zaimplementuj nowy motyw:

/**
 * 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',
    ),
  );
}

A następnie dodaj formularz - szablon user_login.tpl.php z kodem śledzenia, aby wyświetlić formularz:

<?php print drupal_render_children($form) ?> 

1
Ta #themewłaściwość jest bardzo prosta i jest wymieniona po raz pierwszy bardzo nisko w odpowiedziach, bardzo dziwna. To zdecydowanie moja ulubiona metoda.
Matt Fletcher

1
Przetestowałem ten kod i działa zgodnie z oczekiwaniami.
VladSavitsky,

14

Nawet jeśli możesz skorzystać z rozwiązania kiamlaluno, ja osobiście bym tego nie zrobił.

Jaki jest powód, dla którego potrzebujesz pliku szablonu formularza? Jeśli to dlatego, że chcesz nieco inny znacznik dla istniejącego formularza? Jeśli tak, możesz hook_form_alter()zmodyfikować formularz przed jego renderowaniem. Za pomocą interfejsu API formularza możesz modyfikować wszystkie pola formularza, wstawiać elementy HTML itp.

Oto przykład hook_form_alter(), który stworzyłem, który modyfikuje standardowy blok formularza logowania 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;
  }
}

Powyższy przykład otacza całą formę w DIV, który ma styl wbudowany, aby zmienić kolor tła na czerwony. Dodaje również akapit tekstu pomocy na początku formularza.

Tak wygląda teraz mój formularz logowania użytkownika po załadowaniu powyższego kodu:

Dostosowany formularz logowania

Aby uzyskać więcej informacji, zobacz Dokumentacja interfejsu API formularza : Dokumentacja interfejsu API formularza


1
Aby wyjaśnić użycie stylów wbudowanych w tym przykładzie, wystarczy uprościć przykład. Nie polecam używania stylów wbudowanych i powinieneś używać klas.
Camsoft,

Nie obsługuję używania pliku szablonu do renderowania formularza; w rzeczywistości powiedziałem również, że nigdy nie użyłem pliku szablonu do renderowania formularza (faktycznie zmieniłem kod modułu, który używał pliku szablonu dla formularza) i że Drupal nie używa szablonu pliki do renderowania formularzy.
kiamlaluno

5
Co jeśli chcesz radykalnie zmienić znaczniki? Czasami plik szablonu jest lepszą opcją.
kossowicz

6
Znaczniki w formie kreatora logiki pachną.
Charlie Schliesser

1
Chociaż to rozwiązanie działa w większości przypadków, może się zepsuć, gdy renderowanie formularza jest odświeżane w wywołaniu zwrotnym ajax
PatrickS

13

Tak naprawdę nigdy nie potrzebowałem używać pliku szablonu dla formularza.
O ile widzę, podstawowy kod Drupala używa funkcji motywu, gdy formularz lub część formularza musi być renderowana w określony sposób; funkcja motywu wywołująca drupal_render () zwykle wystarcza do jakichkolwiek celów.

Aby odpowiedzieć na pytanie, utworzenie pliku szablonu dla formularza nie różni się od utworzenia pliku szablonu, który nie jest dla formularza.

Zdefiniuj funkcję motywu, używając jako funkcji motywu nazwy wywołania zwrotnego konstruktora formularzy. Kod powinien być podobny do następującego:

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

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

Jeśli formularz zawiera wartość $form['field_1'], jej wartość będzie dostępna w pliku szablonu jako $field_1. Plik szablonu będzie mógł także używać dowolnych wartości przekazywanych z template_preprocess_mymodule_form().


Jak zasugerować formularz zdefiniowany przez inne moduły, być może moduły podstawowe, aby użyć mojej funkcji / szablonu kompozycji?
Shafiul

Set $form['#theme'].
kiamlaluno

1
Nie działa, gdy prześlę formularz, nie przejdzie on do funkcji
form_submit

1

Zawsze stylizowałbym, dodając do mojego pliku CSS za pomocą selektorów, aby zidentyfikować element, który ma być stylowany w następujący sposób dla podstawowego formularza logowania

#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;
}

Powyższe po prostu dodaję sites/all/themes/theme-name/css/theme-name.css

Jeśli to, czego potrzebujesz do stylu, nie ma identyfikatora ani wystarczająco dokładnego selektora, konieczne jest zastosowanie hookpodejścia do zmodyfikowania kodu HTML i dodanie identyfikatorów.

IMO używająca stylu wbudowanego w elementach jest bardzo złą praktyką, która powinna być przestarzała i zastąpiona przez użycie classiid


0

Aby utworzyć motyw formularza, możesz użyć niestandardowego css, jak wyjaśniono w Themeing Drupal 7 Forms (w tym CSS i JS) .

Zasadniczo musisz wykonać następujące kroki:

  1. Zarejestruj ścieżkę do formularza za pomocą hook_menu ()
  2. Zdefiniuj formularz
  3. Zarejestruj funkcję motywu za pomocą hook_theme ()
  4. Napisz funkcję motywu
  5. Utwórz pliki CSS i JavaScript

-2

Jestem pewien, że możesz użyć szablonu do formularzy, ale musisz najpierw użyć hook_theme, aby zarejestrować szablon. Miałem sytuację, w której formularz naprawdę musiał być oparty na tabeli, a nie na div, a proste zmiany #prefix i #suffix tak naprawdę go nie wycięły. W razie zainteresowania mógłbym prawdopodobnie spróbować wykopać przykład.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.