0

I'm attempting to allow a user to add text fields by clicking a button in a configuration form for a block plugin. I'm currently populating the form like so:

public function blockForm($form, FormStateInterface $form_state) {
    for ($i = 0; $i < $this->configuration['linkNum_submit']; $i += 1) {
        $form['link'][$i] = array(
            '#type'          => 'textfield',
            '#title'         => 'Link',
            '#default_value' => '',
        );
    }

My form is populated using a for loop that takes into account a configuration field noting the amount of textfields that should be displayed.

I also have a button that's meant to add another $form['link'] textfield by doing an ajax callback.

$form['add_link'] = array(
    '#type'     => 'button',
    '#value'    => $this->t('Add link'),
    '#ajax'     => [
        'callback' => array($this, 'Drupal\my_module\Plugin\Block\LinkList::addLink'),
        'event'    => 'click',
        'progress' => array(
            'type'    => 'throbber',
            'message' => t('Adding link...'),
        ),
    ],
);

Below is the ajax function that is called. It attempts to increase the configuration field the for loop in bockForm is based on.

public function addlink(array&$form, FormStateInterface $form_state) {
    $response = new AjaxResponse();
    $this->configuration['linkNum_submit'] += 1;

    return $response;
}

I believe my issue is that the form isn't being rebuilt, but I'm not sure how to force it to. I found documentation on the rebiuldForm() function here https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Form!FormBuilder.php/function/FormBuilder%3A%3ArebuildForm/8.2.x but I'm not sure how to implement it in this case.

1 Answer 1

2

The issue is not about the form rebuild, the form is being automatically rebuilt on every AJAX call. The issue here is of the wrapper is not being defined in the '#ajax' array and the wrapper attribute should be given to a "container" type of field and then all of the updated fields should be part of the respective "container" field.

or some ajax command should be called on $response object in the ajax callback method above.

e.g.

public function blockForm($form, FormStateInterface $form_state) {

$form['link'] = array(
  '#type' => 'container',
  '#attributes' => array('id' => 'link-wrapper'),
);
for ($i = 0; $i < $this->configuration['linkNum_submit']; $i += 1) {
    $form['link'][$i] = array(
        '#type'          => 'textfield',
        '#title'         => 'Link',
        '#default_value' => '',
    );
$form['add_link'] = array(
  '#type'     => 'button',
  '#value'    => $this->t('Add link'),
  '#ajax'     => [
    'callback' => array($this, 'addLink'),
    'event'    => 'click',
    'wrapper' => 'link-wrapper',
    'progress' => array(
        'type'    => 'throbber',
        'message' => t('Adding link...'),
    ),
],

);

and then in the ajax callback

public function addlink(array&$form, FormStateInterface $form_state) {
  return $form['flipper']['front']['settings']['link'];
}
2

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.