0

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!

2
  • 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.
    – 4uk4
    Nov 17, 2022 at 12:59
  • @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?
    – techenzie
    Nov 18, 2022 at 7:48

1 Answer 1

1

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',
  ],
];
2
  • 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.
    – techenzie
    Nov 18, 2022 at 11:33
  • 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.
    – 4uk4
    Nov 18, 2022 at 12:29

Your Answer

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

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