0

In my case, I need to get a list of config files to show in a form element. Extending from this Drupal Answers Q/A using form_state->set() inside ajax callback but cannot get the value back outside the callback, I see a suggested way of calling a static function in the submit.

However, I am missing some understanding of how to properly execute.

$list = '';

$form['fieldset'] = [
  '#type' => 'fieldset',
  '#prefix' => '<div id="wrapper">',
  '#suffix' => '</div>',
];

$form['fieldset']['list'] = [
  '#type' => 'item',
  '#title' => t('List'),
  '#description' => $list,
];

$form['fieldset']['submit'] = [
  '#type' => 'submit',
  '#value' => $this->t('Submit'),
  '#submit' => [static::class, 'customFunction'],
  '#ajax' => [
    'callback' => '::customCallback',
    'wrapper' => 'wrapper',
  ],
];

public function customCallback(array &$form, FormStateInterface $form_state) {
  $list = $form_state->get('list');
  $form_state->setRebuild(TRUE);
}

public static function customFunction(array &$form, FormStateInterface $form_state) {
  $form_state->set('list', $li);
}

How does one get $form_state value into a form element from an ajax button submit function?

Update:

Here is what I have working for this case thanks to @No Sssweat.

public function buildForm(array $form, FormStateInterface $form_state) {

  $form['fieldset']['list'] = [
    '#type' => 'item',
    '#title' => t('List'),
    '#description' => '',
  ];

  $form['fieldset']['submit'] = [
    '#type' => 'submit',
    '#value' => $this->t('Submit'),
    '#submit' => [static::class, 'customFunction'],
    '#ajax' => [
      'callback' => '::customCallback',
      'wrapper' => 'wrapper',
    ],
  ];

}

public function customCallback(array &$form, FormStateInterface $form_state) {

  $values = $form_state->getValues();
  $li = [];
  $config_path = drupal_get_path('module', $values['fieldset']['module_name']) . $values['fieldset']['directory_path'];

  if (is_dir($config_path)) {
    if ($dh = opendir($config_path)) {
      while (($fileName = readdir($dh)) !== false) {
        if (pathinfo($fileName, PATHINFO_EXTENSION) == 'yml') {
          $fileName = str_replace('.yml', '', $fileName);
          $li[] = $fileName;
        }
      }
      closedir($dh);
    }
  }

  $markup = new TranslatableMarkup(
    '<ul>@li</ul>', [
      '@li' => t('<li>' . implode('</li><li>', $li) . '</li>'),
    ]
  );

  $form['fieldset']['list']['#description'] = $markup;
  return $form['fieldset'];
}

public static function customFunction(array &$form, FormStateInterface $form_state) {
  // Empty.
}

But this avoids the question as asked.

1 Answer 1

2

Should be:

public function customCallback(array &$form, FormStateInterface $form_state) {
  $list = $form_state->get('list');
  $form['fieldset']['list']['#description'] = $list;
  return $form['fieldset'];
}
3
  • 1
    Yes, this is the correct answer. The ajax callback has to return either $form or an ajax response. But it shouldn't modify $form, this should have been done already in the form build.
    – 4uk4
    Commented May 8, 2019 at 7:06
  • I've added to my question. I could not get ->set/->get to work through the custom functions. Could this be because of the $form['fieldset']['list'] element type? Commented May 8, 2019 at 17:53
  • 1
    @Prestosaurus it's because '#type' => 'item',. Item type does not have a value. If you set it to '#type' => 'textfield', and then put some text on the text-box, you should see the description change to that after ajax.
    – No Sssweat
    Commented May 9, 2019 at 8:01

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.