Score:2

Block Settings inside Form

in flag

Please I need help with my code. I have a form and a block created programmatically. The block embeds the form to show it on the frontend. The block also has some settings (form preffix text). I want to load the block settings inside my buildForm in my Form.php to get the preffix text and show it in the form markup field. But I can't seem to find a way to pass on the $block_id to the buildForm() so it can load the block.

I have a scenario where there can be two of these blocks on the same page in which Drupal uniques the block by appending some ID with the block id. So for example my page has two of these blocks one would be like feedbackblock the other would be feedbackblock_2 hence I cannot hardcode the block id to load it in my buildForm function.

I want it to dynamically pass on the block id to the form.

build() from my Block.php:

  public function build() {
    $block_id // get the block id of the current block instance
    $feedback_form = $this->formBuilder->getForm(FeedbackForm::class, $block_id);

    $build = [];
    $build['#theme'] = 'feedback_block';
    $build['feedback_block']['#markup'] = render($feedback_form);

    return $build;
  }

buildForm from my FeedbackForm.php:

  public function buildForm(array $form, FormStateInterface $form_state, string $block_id) {
      // Get the block id here.
  }

Is there any way to achieve this?

Kevin avatar
in flag
$feedback_form is already a render array, you don't have to render it. Just set it to a variable, let Drupal do the work.
Kevin avatar
in flag
Also: https://drupal.stackexchange.com/a/199929/57
New To 'C' avatar
in flag
Thanks for the link but I already viewed that and that will not work in my case as I don't have a routing.yml and I don't need one. I am just creating a block and a form block is showing that form and the block can be shown anywhere on the site regardless of a route.
Kevin avatar
in flag
You don't need a routing yaml. Read the answer. " when using parameters in forms you have to set a null value in the parameter list"
New To 'C' avatar
in flag
Oh thanks mate! This worked, I wish I could upvote your comment but don't have the option. I am now able to pass extra arg to the buildForm(). But how can I dynamically get the block id of the current block instance?
Kevin avatar
in flag
I don't understand what you mean dynamically get?
New To 'C' avatar
in flag
For example my page have two of these blocks so Drupal assigns unique IDs (machine-names) to them. One would be like feedbackblock and other would go like feedbackblock_2 this is default Drupal behavior not something I am doing. Drupal uniques the blocks if there are two on same page. So how can I get this unique machine-name for each of them and pass it on to buildForm() ?
Score:2
cn flag

There is an abstaction layer between the storage of the block config and the block view building. Block configuration can be stored anywhere and doesn't necessarily have a machine name. You can however transfer the machine name to the block settings when you place a block in Block Layout:

use Drupal\block\BlockInterface;

/**
 * Implements hook_ENTITY_TYPE_presave() for block entities.
 */
function mymodule_block_presave(BlockInterface $block) {
  if ($block->isNew()) {
    $settings = $block->get('settings');
    $settings['block_id'] = $block->get('id');
    $block->set('settings', $settings);
  }
}

Then you can get the machine name in build():

  public function build() {
    // get the block id of the current block instance
    $block_id = !empty($this->configuration['block_id']) ? $this->configuration['block_id'] : '';

As a side note. I don't think the rest of the code in the question does work. You need to add the unique ID to the form instance before you call formBuilder->getForm() and then use it to build a unique form ID. After that buildForm() can get the ID from the class property. See Using the same form more than once per page with AJAX callbacks

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.