Goal: Have a custom page that shows various elements including links, logos, images and a custom form to help the users reset their passwords (we have a custom reset password interface which sends the user a code so we are over-riding the default reset password interface).

Problem: The submit button is not firing the submitForm function on the reset password form.

Here is my code now:

In my module:

function example_theme($existing, $type, $theme, $path) {
  return array(
    'reset_password' => array(
            'variables' => array(
                'form' => NULL,
                'url'=> '',
                'main_logo_url' => '',
                'foot_logo_url' => '',

In my routing:

  path: '/reset-password'
    _controller: '\Drupal\example\Controller\ResetPasswordController::resetPassword'
    _title: 'Reset password'
    _permission: 'access content'

In my Controller:

namespace Drupal\example\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormState;

class ResetPasswordController extends ControllerBase {
  public function resetPassword() {

    //code here that sets the variables in the return array

    $form_state = new FormState();
    $reset_password_form = \Drupal::formBuilder()->getForm('Drupal\example\Form\ResetPasswordForm', $form_state);

    return array(
      '#theme' => 'reset_password',
      '#form' => $reset_password_form,
      '#url' => $url,
      '#main_logo_url' => $main_logo_url,
      '#foot_logo_url' => $foot_logo_url,

in my form:

namespace Drupal\example\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

class ResetPasswordForm extends FormBase {
  public function getFormId() {
    return 'reset_password';

  public function buildForm (array $form, FormStateInterface $form_state) {
    \Drupal::logger('rp-form')->notice('hello from build Form');
    $form['#theme'] = 'reset_password';

    $form['step_one_user_exists'] = [
      '#type' => 'textfield',
      '#required' => TRUE,
      '#attributes' => array(
        'placeholder' => t('Enter here')

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

    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Send Code'),

    return $form;

  public function validateForm (array &$form, FormStateInterface $form_state) {
    \Drupal::logger('rp-form')->notice('hello from validate');

  public function submitForm (array &$form, FormStateInterface $form_state) {
   \Drupal::logger('rp-form')->notice('hello from submit');

and in my twig template:

// I have other elements on the page here
 {{ form.step_one_user_exists }}
 {{ form.actions.submit }}

As I said above, the problem is that the submitForm function from the form class is not firing when I click the submit button. The form shows up on the page, you can type in the text field, you can click the button, but then nothing happens. I have loggers in the buildForm (which logs), and in validateForm and submitForm (which do not log).

I want to use a controller because there are other variables needed on the page that change based on language and other factors, but am open to other methods of doing this (although I'd prefer to keep most of the logic out of the template).


  • You are using the same template twice, in the controller and inside of the form. This doesn't make sense.
    – 4uk4
    Aug 20, 2020 at 7:22
  • Carefully with property form_build_id, form_token, form_id. You have to render them in your twig template.
    – MrD
    Aug 20, 2020 at 8:44
  • @MrD, it's unclear what twig template this is. We have three possibilities, the one in the controller, the form wrapper form.html.twig and the one defined inside of the form $form['#theme']. Those three would be nested inside of each other. The first and the last one need their own theme hook, the middle one is a core template.
    – 4uk4
    Aug 20, 2020 at 8:54
  • @4k4 thanks for the questions. I do render the form_build_id, form_token and form_id at the top of the form (just didn't include it here for brevity). The template that the form elements are displayed in is the reset-pasword.html.twig within the module and that is displayed by page.html.twig in our main custom theme.
    – dylhof
    Aug 20, 2020 at 15:28

1 Answer 1


The code in the question is mixing three different types of templates:

  1. Custom twig template in a controller


  2. Overriding form.html.twig

    How to Create twig template files in drupal 8 for customizing user login,profile edit and forget password forms?

  3. Adding a custom form template

    How to render specific form elements from the *.theme file

The confusing part of your question is that you are using the same template reset-pasword.html.twig for 1. and 3.

The issue discussed in the comments about the special form elements applies only to 2.

You can use all three template levels at the same time. Then they are nested inside of each other which you see when you enable twig debugging.

More info Custom registration twig template.

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.