Bagaimana cara menggunakan file templat untuk tema formulir?

50

Sementara node, komentar, blok dan banyak hal lainnya di Drupal bertema menggunakan file templat tema (seperti node.tpl.php), form adalah cerita yang berbeda. Tidak ada file templat tema untuk formulir. Bagaimana saya bisa mendapatkan formulir tertentu untuk menggunakan templat tema khusus?

Chaulky
sumber

Jawaban:

73

Sangat masuk akal jika ingin menggunakan file tpl untuk menampilkan formulir. Anda dapat menggunakan banyak CSS dan #prefix/ #suffixproperti asing untuk mendapatkan hasil yang serupa, tetapi dengan menggunakan tpl, Anda tidak perlu mengacaukan pemisahan logika dan lapisan presentasi Anda dan tidak harus menargetkan pemilih CSS yang jelek seperti #user-login label. Berikut ini contoh dalam 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); ?>

Ini menggunakan Foundation , yang memberi kita formulir seperti ini:

masukkan deskripsi gambar di sini

Charlie Schliesser
sumber
sepertinya Anda lupa keadaan kembali pada fungsi mytheme_theme ()
sel_space
Anda benar, saya telah menambahkannya.
Charlie Schliesser
5
Catatan yang sangat penting adalah bahwa, di bagian bawah cuplikan kode, adalah print drupal_render_children($form)yang membuat formulir benar-benar melakukan hal-hal :).
Chris Rockwell
Jawaban yang bagus. Saya dapat menambahkan bahwa Anda perlu menentukan tambahan engine, jika Anda menggunakan sesuatu yang tidak standar. Misalnya 'engine' => 'twig'.
milkovsky
1
Jawaban bagus. Ingatlah jika Anda ingin tema bentuk admin seperti user_profile_formatau user_register_form. Dalam skenario itu Anda harus a) melakukan tema Anda di tema admin (atau subtema dari itu jika Anda tidak dapat mengubah tema admin dasar) atau b) menempatkan tema Anda dalam modul khusus. Kalau tidak, tema Anda tidak akan terlihat.
therobyouknow
18

Anda harus mengimplementasikan hook_form_alter () dalam modul atau template.php dan mengatur properti tema # form :

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

Kemudian terapkan tema baru:

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

Dan kemudian tambahkan formulir - template user_login.tpl.php dengan mengikuti kode untuk membuat formulir:

<?php print drupal_render_children($form) ?> 
mrded
sumber
1
The #themeproperti adalah sangat sangat sederhana dan disebutkan untuk pertama kalinya benar-benar rendah di dalam jawaban, super aneh. Ini jelas merupakan metode favorit saya.
Matt Fletcher
1
Saya menguji kode ini dan berfungsi seperti yang diharapkan.
VladSavitsky
14

Meskipun Anda mungkin dapat menggunakan solusi kiamlaluno, saya pribadi tidak akan melakukannya.

Apa alasan Anda membutuhkan file templat untuk formulir? Jika itu karena Anda ingin markup yang sedikit berbeda untuk formulir yang ada? Jika demikian maka Anda dapat menggunakan hook_form_alter()untuk mengubah formulir sebelum diberikan. Menggunakan Formulir API Anda, Anda dapat memodifikasi semua bidang formulir menyuntikkan elemen html dll.

Berikut adalah contoh hook_form_alter()yang saya buat yang memodifikasi blok form login drupal standar:

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

Contoh di atas membungkus seluruh formulir dalam DIV yang memiliki gaya sebaris untuk mengubah warna latar belakang menjadi merah. Itu juga menambahkan paragraf teks bantuan ke awal formulir.

Seperti inilah bentuk login pengguna saya sekarang setelah kode di atas dimuat:

Formulir login yang disesuaikan

Lihat referensi API Formulir untuk informasi lebih lanjut: Referensi API Formulir

Camsoft
sumber
1
Hanya untuk memperjelas penggunaan gaya inline dalam contoh ini hanya untuk menyederhanakan contoh. Saya tidak merekomendasikan menggunakan gaya inline dan Anda harus menggunakan kelas.
Camsoft
Saya tidak mendukung menggunakan file templat untuk merender formulir; sebenarnya, saya juga mengatakan bahwa saya tidak pernah menggunakan file templat untuk membuat formulir (saya sebenarnya telah mengubah kode modul yang menggunakan file templat untuk formulir), dan bahwa Drupal tidak menggunakan templat file ke membuat formulir.
kiamlaluno
5
Bagaimana jika Anda ingin secara radikal mengubah markup? Terkadang file templat adalah opsi yang lebih baik.
cossovich
6
Markup dalam bentuk pembangun logika bau.
Charlie Schliesser
1
Meskipun solusi ini berfungsi dalam banyak kasus, itu mungkin benar-benar pecah ketika rendering formulir di-refresh dalam panggilan ajax
PatrickS
13

Sebenarnya saya tidak pernah perlu menggunakan file templat untuk formulir.
Sejauh yang saya bisa lihat, kode inti Drupal menggunakan fungsi tema, ketika formulir, atau bagian dari formulir perlu dirender dengan cara tertentu; fungsi tema yang memanggil drupal_render () biasanya cukup untuk tujuan apa pun.

Untuk membalas pertanyaan, membuat file templat untuk formulir tidak berbeda dari membuat file templat yang bukan untuk formulir.

Tentukan fungsi tema, gunakan sebagai fungsi tema nama pemanggil formulir pembangun. Kode harus serupa dengan yang berikut:

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

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

Jika formulir berisi nilai $form['field_1'], nilainya akan tersedia di file templat sebagai $field_1. File template juga dapat menggunakan nilai apa pun yang diteruskan template_preprocess_mymodule_form().

kiamlaluno
sumber
Bagaimana saya menyarankan formulir yang didefinisikan oleh beberapa modul lain, mungkin modul inti untuk menggunakan fungsi / templat tema saya?
Shafiul
Setel $form['#theme'].
kiamlaluno
1
Tidak berfungsi, ketika saya mengirimkan formulir, itu tidak akan pergi ke fungsi
form_submit
1

Saya akan selalu gaya dengan menambahkan ke file CSS saya menggunakan penyeleksi untuk mengidentifikasi elemen yang akan ditata sebagai berikut untuk formulir login inti

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

Di atas saya hanya menambahkan sites/all/themes/theme-name/css/theme-name.css

Jika apa yang Anda perlu gaya tidak memiliki ID atau pemilih yang cukup akurat maka perlu menggunakan hookpendekatan untuk memodifikasi HTML juga menambahkan pengidentifikasi.

IMO menggunakan gaya inline pada elemen adalah praktik yang sangat buruk yang harus ditinggalkan dan diganti dengan menggunakan classdanid

Richard Harrison
sumber
0

Untuk tema formulir, Anda dapat menggunakan custom css, seperti yang dijelaskan dalam Themeing Drupal 7 Forms (Termasuk CSS dan JS) .

Pada dasarnya Anda perlu melakukan langkah-langkah ini:

  1. Daftarkan jalur ke formulir menggunakan hook_menu ()
  2. Tentukan formulirnya
  3. Daftarkan fungsi tema dengan hook_theme ()
  4. Tulis fungsi tema
  5. Buat file CSS dan JavaScript
shasi kanth
sumber
-2

Saya cukup yakin Anda dapat menggunakan templat untuk formulir, tetapi Anda harus menggunakan hook_theme untuk mendaftarkan templat di tempat pertama. Saya punya situasi di mana formulir benar - benar perlu berbasis tabel daripada berbasis div dan perubahan #prefix dan #suffix sederhana tidak benar-benar memotongnya. Jika tertarik saya mungkin bisa mencoba dan menggali contoh.

Malks
sumber