3

I want to be able to theme a custom form I create using a custom module that builds a form. The form is created programmatically using the code below:

public function buildForm(array $form, FormStateInterface $form_state) {

    $form['name'] = array(
      '#type' => 'textfield',
      '#title' => $this->t('Name'),
      '#required' => TRUE
    );

    $form['address'] = array(
      '#type' => 'textfield',
      '#title' => $this->t('Address'),
      '#required' => TRUE
    );

    $form['actions']['submit'] = array(
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
    );

    return $form;
}

This form is rendered on the Drupal 8 back-end and uses the admin theme classy BEGIN OUTPUT from 'core/themes/classy/templates/form/form.html.twig'. However there isn't a override file name suggestion.

How would I theme this form?

4 Answers 4

4

I was looking for a way to use a twig template to theme the form. How would I go about doing that?

First your form needs to have an ID

public function buildForm(array $form, FormStateInterface $form_state) {

    $form['name'] = array(
      '#type' => 'textfield',
      '#title' => $this->t('Name'),
      '#required' => TRUE
    );

    $form['address'] = array(
      '#type' => 'textfield',
      '#title' => $this->t('Address'),
      '#required' => TRUE
    );
    $form['actions'] = array('#type' => 'actions');
    $form['actions']['submit'] = array(
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
    );

    return $form;
}

public function getFormId() {
  return 'the_custom_form_id';
}

Now we create a new suggestion:

mymodule/mymodule.module

<?php

use Drupal\Core\Form\FormStateInterface;

/**
 * Implements hook_theme_suggestions_alter
 */
function mymodule_theme_suggestions_alter(array &$suggestions, array $variables) {

    if (isset($variables['element']) && isset($variables['element']['#type']) && $variables['element']['#type'] == 'form') {
        $original_theme_hook = $variables['theme_hook_original'];

        $suggestions[] = $original_theme_hook . '__' . str_replace('-', '_', $variables['element']['#id']);
    }

    return $suggestions;

}

/**
 * Implements hook_form_alter()
 */    
function mymodule_form_alter(&$form, FormStateInterface $form_state, $form_id) {

    if ($form_id == 'the_custom_form_id') {

      $form['#theme'] = ['my_custom_form'];

    }

}

/**
 * Implements hook_theme()
 */
function mymodule_theme() {

    $themes['my_custom_form'] = ['render element' => 'form'];

    return $themes;

}

Note: If you're the creator of the form, you can skip the hook_form_alter part and just put $form['#theme'] = ['my_custom_form']; inside your form

mymodule/templates/my_custom_form.html.twig

<div class="something">{{ form.name }}</div>
<div class="something-else">{{ form.address }}</div>
<div class="something-else2">{{ form.actions }}</div>
4
  • @Harnamc You're welcome, no prob.
    – No Sssweat
    Commented Jan 27, 2017 at 14:08
  • hey, this works for me kind of, but I am a little confused with your note, where I should place this $form['#theme'] = ['my_custom_form']; inside formbuild function? I tried that and didn't work. If I use form_alter then I can't save fields information on database. Can you help me with this? thanks
    – Pedro
    Commented Feb 9, 2021 at 18:22
  • @Pedro Hmm, yes try putting it in the build function, but without the named wrapped in an array. $form['#theme'] = 'my_custom_form'; If it still doesn't work, then maybe I am wrong.
    – No Sssweat
    Commented Feb 10, 2021 at 9:50
  • I am passing theme value inside an array like this $form['module']['admin_theme'] = array( '#theme' => 'admin_form' ); And twig file is loaded, but now I can't call my fields like you explain {{ form.name }} My fields appear but like an admin form as usual If I apply alterForm I can load my fields like you said, but submit button is not doing anything, any ideas for submit button not working (save values in database) ?
    – Pedro
    Commented Feb 10, 2021 at 12:00
4

One option is to add a prefix and suffix to your form arrays

$form['name'] = array(
  '#type' => 'textfield',
  '#title' => $this->t('Name'),
  '#required' => TRUE
  '#prefix' => '<div class="something">',     
  '#suffix' => '</div>',
);

$form['#attached']['css'] = array(
 'path/to/my.css' => array(
   'group' => CSS_AGGREGATE_THEME,
   'weight' => 999
 ),
);

my.css

.something { 
  border: solid red;
}
1
  • I was looking for a way to use a twig template to theme the form. How would I go about doing that?
    – harnamc
    Commented Jan 27, 2017 at 8:41
2

It's an old post but it help me someway, so I will leave my answear, hope it will help someone.

The first answear of this post help me a lot, at the end I simplify some code.

I had same problem when I try to theme my form.

What I have done

MYMODULE.module file.

function MYMODULE_theme($existing, $type, $theme, $path) {
  return [
    'admin_form' => [
      'template' => 'admin-form',
      'render element' => 'form',
    ],
  ];
}

The on my form.php (MYMODULE/scr/Form/form.php) inside buildForm function

$form['simulator_values']['connection_services'] = [
  '#type' => 'textfield',
  '#maxlength' => 140,
  '#default_value' => $config->get('connection_services'),
  '#required' => TRUE,
];

$form['actions'] = [
  '#type' => 'actions'
];

$form['actions']['submit'] = [
  '#type' => 'submit',
  '#value' => $this->t('Submit ss')
];

return [
  '#theme' => 'admin_form',
  'render element' => $form,
];

Finally on twig side have to build form like this

<form {{ attributes }}>
  {{ form.form_build_id }}
  {{ form.form_token }}
  {{ form.form_id }}
  {{ form['render element'].advanced_info }}
  {{ form['render element'].actions.submit }}
</form>

Without form_build_id, form_token and form_id the submit button won't work.

As far I understood drupal need those information about the form to process everything on the right way, because you can have multiple forms on the same page.

0

Please have a look at the Formdazzle! module.

Drupal form theming with less pain Theming drupal forms can be difficult and time-consuming. This module provides a set of utilities that make form theming easier.

Currently, this module provides theme suggestions for forms that are much more useful than those provided by Drupal core.

  • Theme suggestions for all form elements (including buttons)
  • Theme suggestions for all form element labels
  • All theme suggestions include the form ID and the form element name; e.g. [element-type]--[form-id]--[form-element-name].html.twig
  • New in 2.1.0! Twig debugging comments have been added to all forms for the hidden [form-id].html.twig template.

While Drupal core only provided these two theme suggestions:

input.html.twig
input--textfield.html.twig

Formdazzle adds the following two theme suggestions to the list:

input--textfield--webform-contact.html.twig
input--textfield--webform-contact--first-name.html.twig

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.