Wie verwende ich eine Vorlagendatei, um ein Formular zu gestalten?


50

Während Knoten, Kommentare, Blöcke und viele andere Dinge in Drupal unter Verwendung von Designvorlagendateien (wie node.tpl.php) thematisiert werden, sind Formulare eine andere Geschichte. Es gibt keine Designvorlagendateien für Formulare. Wie kann ich ein bestimmtes Formular zur Verwendung einer benutzerdefinierten Designvorlage anfordern?

Antworten:


73

Es ist durchaus sinnvoll, eine tpl-Datei zum Anzeigen eines Formulars zu verwenden. Sie können viele irrelevante CSS- und #prefix/ oder CSS- #suffixEigenschaften verwenden, um ähnliche Ergebnisse zu erzielen. Mit tpls müssen Sie jedoch nicht die Trennung von Logik- und Präsentationsebenen überfrachten und keine hässlichen CSS-Selektoren wie auswählen #user-login label. Hier ist ein Beispiel in 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); ?>

Hierfür wird Foundation verwendet. Dies gibt uns ein Formular wie das folgende:

Bildbeschreibung hier eingeben


Es sieht so aus, als hätten Sie einen Rückgabestatus für die Funktion mytheme_theme () vergessen
sel_space

Du hast recht, ich habe es hinzugefügt.
Charlie Schliesser

5
Sehr wichtiger Hinweis ist, dass sich am Ende des Code-Snippets befindet print drupal_render_children($form), wodurch das Formular tatsächlich Dinge tut :).
Chris Rockwell

Gute Antwort. Ich kann hinzufügen, dass Sie zusätzlich angeben müssen engine, wenn Sie etwas nicht Standard verwenden. Eg 'engine' => 'twig'.
Milkovsky

1
Gute Antwort. Denken Sie daran, wenn Sie ein Admin-Formular wie user_profile_formoder thematisieren möchten user_register_form. In diesem Szenario müssen Sie entweder a) Ihre Themes im Admin-Design erstellen (oder davon entfernen, wenn Sie das Basis-Admin-Design nicht ändern können) oder b) Ihre Themes in ein benutzerdefiniertes Modul einfügen. Andernfalls wird Ihr Thema nicht angezeigt.
wissen,

18

Sie müssen hook_form_alter () in einem Modul oder einer template.php implementieren und die # theme- Eigenschaft des Formulars festlegen :

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

Dann implementiere ein neues Theme:

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

Fügen Sie dann die Vorlage form - user_login.tpl.php mit folgendem Code hinzu, um das Formular zu rendern:

<?php print drupal_render_children($form) ?> 

1
Die #themeEigenschaft ist so sehr einfach und wird zum ersten Mal wirklich tief in den Antworten erwähnt, super komisch. Dies ist definitiv meine Lieblingsmethode.
Matt Fletcher

1
Ich habe diesen Code getestet und er funktioniert wie erwartet.
VladSavitsky

14

Auch wenn Sie möglicherweise in der Lage sind, die Lösung von kiamlaluno zu verwenden, würde ich dies persönlich nicht tun.

Aus welchem ​​Grund benötigen Sie eine Vorlagendatei für ein Formular? Liegt es daran, dass Sie für ein vorhandenes Formular ein etwas anderes Markup wünschen? In diesem Fall können Sie hook_form_alter()das Formular vor dem Rendern ändern. Mit der Formular-API können Sie alle Formularfelder ändern, indem Sie HTML-Elemente usw. einfügen.

Hier ist ein Beispiel hook_form_alter(), das ich erstellt habe und das den Standard-Drupal-Anmeldeformularblock ändert:

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

Das obige Beispiel umschließt das gesamte Formular mit einem DIV, der einen Inline-Stil hat, um die Hintergrundfarbe in Rot zu ändern. Außerdem wird am Anfang des Formulars ein Absatz mit Hilfetext eingefügt.

So sieht mein Benutzeranmeldeformular jetzt aus, wenn der obige Code geladen ist:

Benutzerdefiniertes Anmeldeformular

Weitere Informationen finden Sie in der Referenz zur Formular-API: Referenz zur Formular-API


1
Nur um die Verwendung von Inline-Stilen in diesem Beispiel zu verdeutlichen, wird das Beispiel vereinfacht. Ich empfehle nicht, Inline-Stile zu verwenden, und Sie sollten Klassen verwenden.
Camsoft

Ich kann keine Vorlagendatei zum Rendern eines Formulars verwenden. Tatsächlich habe ich auch gesagt, dass ich nie eine Vorlagendatei zum Rendern eines Formulars verwendet habe (ich habe tatsächlich den Code eines Moduls geändert, das eine Vorlagendatei für ein Formular verwendet hat), und dass Drupal keine Vorlage verwendet Dateien zum Rendern von Formularen.
kiamlaluno

5
Was ist, wenn Sie das Markup radikal ändern möchten? Manchmal ist eine Vorlagendatei eine bessere Option.
Cossovich

6
Markup in einem Form Logic Builder riecht.
Charlie Schliesser

1
Obwohl diese Lösung in den meisten Fällen funktioniert, kann sie tatsächlich unterbrochen werden, wenn die Formularwiedergabe in einem Ajax-Rückruf aktualisiert wird
PatrickS

13

Ich brauchte eigentlich nie eine Vorlagendatei für ein Formular.
Soweit ich sehen kann, verwendet der Drupal-Kerncode Themenfunktionen, wenn ein Formular oder ein Teil eines Formulars auf eine bestimmte Weise gerendert werden muss. Eine Theme-Funktion, die drupal_render () aufruft, ist normalerweise für alle Zwecke ausreichend.

Um auf die Frage zu antworten, unterscheidet sich das Erstellen einer Vorlagendatei für ein Formular nicht vom Erstellen einer Vorlagendatei, die nicht für ein Formular bestimmt ist.

Definieren Sie eine Designfunktion, indem Sie als Designfunktion den Namen des Form Builder-Rückrufs verwenden. Der Code sollte ungefähr so ​​aussehen:

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

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

Wenn das Formular den Wert enthält $form['field_1'], ist sein Wert in der Vorlagendatei als verfügbar $field_1. Die Vorlagendatei kann auch alle Werte verwenden, die von übergeben wurden template_preprocess_mymodule_form().


Wie schlage ich ein Formular vor, das von einigen anderen Modulen, möglicherweise Kernmodulen, definiert wurde, um meine Themenfunktion / Vorlage zu verwenden?
Shafiul

Einstellen $form['#theme'].
kiamlaluno

1
Funktioniert nicht, wenn ich das Formular abschicke, wird es nicht an die form_submit-Funktion weitergeleitet
gbstack

1

Ich füge meiner CSS-Datei immer einen Stil hinzu, indem ich Selektoren verwende, um das Element zu identifizieren, das wie folgt für das Hauptanmeldeformular gestaltet werden soll

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

Das obige füge ich einfach hinzu sites/all/themes/theme-name/css/theme-name.css

Wenn das, was Sie formatieren möchten, keine ID oder keinen ausreichend genauen Selektor hat, müssen Sie den hookAnsatz verwenden, um den HTML-Code zu ändern und Bezeichner hinzuzufügen.

IMO mit Inline-Stil für Elemente ist eine sehr schlechte Praxis , die durch die Verwendung von classund ersetzt werden sollteid



-2

Ich bin mir ziemlich sicher, dass Sie eine Vorlage für Formulare verwenden können, aber Sie müssen zunächst hook_theme verwenden, um die Vorlage zu registrieren. Ich hatte eine Situation, in der das Formular wirklich eher tabellenbasiert als div-basiert sein musste und die einfachen Änderungen von #prefix und #suffix es nicht wirklich schnitten. Bei Interesse könnte ich wahrscheinlich versuchen, ein Beispiel zu finden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.