Score:0

submitForm not being called when put inside a Custom Block

lc flag

I have been trying to find a fix for this but I haven't been able to. I have tried to put a form inside a custom block to render the form as a component. When the form is submitted it renders the component again but it doesn't invoke the submitForm function. Please review the code and let me know if you guys understand what the problem is.

This is the file structure for the block

NewsletterForm.php

<?php
/**
 * @file
 * Contains \Drupal\newsletter_block\Form\WorkForm.
 */

namespace Drupal\newsletter_block\Form;

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

class newsletterForm extends FormBase {
  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'newsletter_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {

    $form['newsletter_email_id'] = array(
      '#type' => 'email',
      '#title' => t('E-MAIL'),
      '#required' => TRUE,
    );

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

    return $form;
  }

  public function submitForm(array &$form, FormStateInterface $form_state) {
   
   /**
   * {@inheritdoc}
   */

    $obj = array(
        'newsletter_email_id' => $form_state->getValue('newsletter_email_id'),
    );

    $url = 'http://demo7220892.mockable.io/newsletterblock';
    
    $options = array(
        http => array(
            'header' => "Content-type: application/www-form-urlencoded",
            'method' => 'POST',
            'content' => http_build_query($obj),
        )
        );
    $context = stream_context_create($options);
    $result = file_get_contents($url, false, $context);
    if ($result === FALSE) {
        drupal_set_message(t('Error in sending data to the server. Please try again later!'), 'error');
    }
    else {
        drupal_set_message(t('Thank you for subscribing to our newsletter. We will keep you updated on our latest developments.'));
    }

    var_dump($result);
  }
}

NewsletterBlock.php

<?php
/**
 * @file
 * Contains \Drupal\newsletter_block\Plugin\Block\NewsletterBlock.
 */


namespace Drupal\newsletter_block\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * Provides a 'NewsletterBlock' for the Footer.
 * 
 * @Block(
 *   id = "newsletter_block",
 *   admin_label = @Translation("Newsletter Block"),
 * )
 * 
 */

 class NewsletterBlock extends BlockBase {
    
   /**
   * {@inheritdoc}
   */

  public function build() {
    
    $form = \Drupal::formBuilder()->getForm('Drupal\newsletter_block\Form\NewsletterForm');

    return $form;
  }

}

newsletter-block.html.twig

<div class="newsletterBlock" id="newsletter_block">
    <h4 class="newsletterTitle fw-normal">Newsletter</h4>
    <form>
        <div class="form-group">
            <input class="newsletterEmail fw-normal" name="newsletter_email_id" id="newsletterEmailAddress" aria-describedby="emailHelp" placeholder="E-MAIL"><input type="submit" name="subscribe_button" id="subscribeButton" value="SUBSCRIBE"/>
        </div>
    </form>
</div>

{{ attach_library("newsletter_block/newsletter-block") }}

{{ form.form_build_id }}
{# required #}
{{ form.form_id }}
{# required #}
{{ form.form_token }}
{# required #}

newsletter_block.module

<?php

/**
 * Implements hook_theme().
 */
function newsletter_block_theme($existing, $type, $theme, $path) {
  return [
    'newsletter_block' => [
      'template' => 'newsletter-block',
      'render element' => 'form',
      ],
    ];
}

function newsletter_block_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form_id == 'newsletter_form') {
    $form['#theme'] = 'newsletter_block';
  }
}

The form is being rendered properly but clicking the SUBSCRIBE button does not invoke the submitForm function. I know this because I tried using breakpoints through XDebug. Please help me out with this.

Thank you in advance!

4uk4 avatar
cn flag
There is nothing wrong with the block. It's the template doing something weird by rendering its own form markup. BTW you have pasted the last code segment twice. Perhaps the missing code makes it more clear what you want to do.
techenzie avatar
lc flag
@4uk4 Thank you for your comment. I have replaced the last piece of code with the right one now. Could you have a look and see what might be causing the problem?
Score:1
cn flag

You don't need a form alter hook, you can define the form template

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

in buildForm() of the form class.

Getting the form submitted

The form template needs to render the form elements of the form build provided in the variable form and at the end you can render the rest of form so you don't need to specify all the required internal stuff:

newsletter-block.html.twig

{{ form.newsletter_email_id }}
{{ form.submit }}

{{ form|without('newsletter_email_id', 'submit') }}

Styling form elements

When form elements need specific attributes add them already in buildForm():

$form['newsletter_email_id'] = [
  '#type' => 'email',
  '#title' => t('E-MAIL'),
  '#required' => TRUE,
  '#attributes' => [
    'class' => [
      'newsletterEmail',
      'fw-normal',
    ],
    'aria-describedby' => 'emailHelp',
  ],
];
techenzie avatar
lc flag
I tried to remove the required internal commands and replaced them with the ones that you have provided. Although, now that I added the ```$form['theme'] = 'newsletter_block';``` in the buildForm() func, it now renders two different input areas and buttons. I don't know why this is happening. When the theme is not defined the PHP form works well. Is there a way to connect the PHP and twig variables and render just a single form rather than two forms using the provided css.
4uk4 avatar
cn flag
You probably have still parts of the not working template. Try the template I've posted without adding anything. If this is working add your own styling, but don't add any `<form>` or `<input>` tags yourself. The form tag is added later and the form elements are all in the `form` variable, already processed and ready to be submitted.
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.