BlockForm / Add More Field with autocomplete

Events happening in the community are now at Drupal community events on www.drupal.org.
You are viewing a wiki page. You are welcome to join the group and then edit it. Be bold!

I share with you an example about how you create a block form and manager data with multiple field ( autocomplete ) :

  1. This class for block form "a la une"

<?php

namespace Drupal\mm_content\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\node\Entity\Node;

/**
* Provides a 'ALaUneBlock' block.
*
* @Block(
* id = "ala_une_block",
* admin_label = @Translation("A la une block"),
* )
*/
class ALaUneBlock extends BlockBase {

/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return parent::defaultConfiguration() + [
'articles_alaune' => [],
];
}

/**
* Overrides \Drupal\Core\Block\BlockBase::blockForm().
*
* Adds body and description fields to the block configuration form.
*/
public function blockForm($form, FormStateInterface $form_state) {
$form = parent::blockForm($form, $form_state);
$config = $this->getConfiguration();

$items = [];
if ($config['articles_alaune']) {
  $items = Node::loadMultiple($config['articles_alaune']);
}

$form['#tree'] = TRUE;

$form['items_fieldset'] = [
  '#type' => 'fieldset',
  '#title' => $this->t('List items'),
  '#prefix' => '<div id="items-fieldset-wrapper">',
  '#suffix' => '</div>',
];

if (!$form_state->has('num_items')) {
  $form_state->set('num_items', count($config['articles_alaune']));
}
$name_field = $form_state->get('num_items');
for ($i = 0; $i < $name_field; $i++) {
  $items = array_values($items);
  $form['items_fieldset']['items'][$i] = [
    '#type' => 'entity_autocomplete',
    '#target_type' => 'node',
    '#title' => t('Item'),
    '#description' => t('Use autocomplete to find it'),
    '#selection_handler' => 'default',
    '#selection_settings' => array(
      'target_bundles' => array('article'),
    ),
    '#default_value' => $items[$i],
  ];
}

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

$form['items_fieldset']['actions']['add_item'] = [
  '#type' => 'submit',
  '#value' => t('Add one more'),
  '#submit' => $this, 'addOne',
  '#ajax' => [
    'callback' => [$this, 'addmoreCallback'],
    'wrapper' => 'items-fieldset-wrapper',
  ],
];

if ($name_field > 1) {
  $form['items_fieldset']['actions']['remove_item'] = [
    '#type' => 'submit',
    '#value' => t('Remove one'),
    '#submit' => $this, 'removeCallback',
    '#ajax' => [
      'callback' => [$this, 'addmoreCallback'],
      'wrapper' => 'items-fieldset-wrapper',
    ]
  ];
}

return $form;

}

/**
* @param array $form
* @param \Drupal\Core\Form\FormStateInterface $form_state
*/
public function addOne(array &$form, FormStateInterface $form_state) {
$name_field = $form_state->get('num_items');
$add_button = $name_field + 1;
$form_state->set('num_items', $add_button);
$form_state->setRebuild();
}

/**
* @param array $form
* @param \Drupal\Core\Form\FormStateInterface $form_state
* @return mixed
*/
public function addmoreCallback(array &$form, FormStateInterface $form_state) {
// The form passed here is the entire form, not the subform that is
// passed to non-AJAX callback.
return $form['settings']['items_fieldset'];
}

/**
* @param array $form
* @param \Drupal\Core\Form\FormStateInterface $form_state
*/
public function removeCallback(array &$form, FormStateInterface $form_state) {
$name_field = $form_state->get('num_items');
if ($name_field > 1) {
$remove_button = $name_field - 1;
$form_state->set('num_items', $remove_button);
}
$form_state->setRebuild();
}

/**
* {@inheritdoc}
*/
public function blockSubmit($form, FormStateInterface $form_state) {
foreach ($form_state->getValues() as $key => $value) {
if ($key === 'items_fieldset') {
if (isset($value['items'])) {
$items = $value['items'];
foreach ($items as $key => $item) {
if ($item === '' || !$item) {
unset($items[$key]);
}
}
$this->configuration['articles_alaune'] = $items;
}
}
}
}

/**
* {@inheritdoc}
*/
public function build() {
$nodes = [];

if (isset($this->configuration['articles_alaune'])) {
  if (count($this->configuration['articles_alaune']) > 0) {
    $nids = $this->configuration['articles_alaune'];
    $nodes = Node::loadMultiple($nids);
  }
}

return array(
  '#theme' => 'alaune_block',
  '#nodes' => $nodes
);

}

}

  1. In file .module : we use hook theme to define template twig 

/**
* Implements hook_theme().
*/
function mymodule_theme() {
$path_to_themes = drupal_get_path('module', 'mymodule') . '/templates';

return [
    'alaune_block' => [
        'variables' => [
            'nodes' => null
        ],
        'path' => $path_to_themes . '/block'
    ]
];

}

  1. In last step, we extract data from nodes array :

{% for node in nodes %}

{{ node.title.value }}

{% if node.body.summary %}

{{ node.body.summary | raw }}

{% endif %}

{% endfor %}

Toronto

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: