i´m working on a custom display extender for Views.
The display extender itself works as expected, i´ve taken the code mostly from Studiogd The display extender plugin now i needed in the options form a fieldset with add more button, so i tried to implement/adapt \Drupal\form_api_example\Form\AjaxAddMore for my options form.
But i have a problem calling the submit and ajax callback.
Here is a subset of my display extender that is probalby relevant
namespace Drupal\foo\Plugin\views\display_extender;
use Drupal\views\Plugin\views\display_extender\DisplayExtenderPluginBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Foo display extender plugin.
*
* @ingroup views_display_extender_plugins
*
* @ViewsDisplayExtender(
* id = "foo",
* title = @Translation("Foo"),
* help = @Translation("Foo Bar."),
* no_ui = FALSE
* )
*/
class Foo extends DisplayExtenderPluginBase {
...
/**
* Provide a form to edit options for this plugin.
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
...
$form['foo']['filters_fieldset']['actions']['add_filter'] = [
'#type' => 'submit',
'#value' => $this->t('Add an entry'),
'#submit' => [
'::addFilterEntry', // <---- Taken from example
],
'#ajax' => [
'callback' => '::filtersFieldsetCallback',
'wrapper' => 'filters-fieldset-wrapper',
],
];
...
}
...
/**
* Submit handler for the "add-one-more" button.
*
* Increments the max counter and causes a rebuild.
*/
public function addFilterEntry(array &$form, FormStateInterface $form_state) {
$filter_field = $form_state->get('num_filters');
$add_button = $filter_field + 1;
$form_state->set('num_filters', $add_button);
// Since our buildForm() method relies on the value of 'num_filters' to
// generate 'filter' form elements, we have to tell the form to rebuild. If we
// don't do this, the form builder will not call buildForm().
$form_state->setRebuild();
}
/**
* Callback for both ajax-enabled buttons.
*
* Selects and returns the fieldset with the filters in it.
*/
public function filtersFieldsetCallback(array &$form, FormStateInterface $form_state) {
return $form['foo']['filters_fieldset'];
}
...
}
Now when i click the add more button in the options form it Results in:
call_user_func_array() expects parameter 1 to be a valid callback, class 'Drupal\views_ui\Form\Ajax\Display' does not have a method 'addFilterEntry'
So I tried to specify it like:
'#submit' => [
[$this, 'addFilterEntry'],
],
which actually lets call_user_func try to call 'addFilterEntry' on my class and i get
The specified #ajax callback is empty or not callable.
makes sense, now when I also change the ajax callback to
'#ajax' => [
'callback' => [$this, 'filtersFieldsetCallback'],
I cant open the options form anymore resulting in a 5xx response
InvalidArgumentException: Recursion detected in Symfony\Component\HttpFoundation\JsonResponse->setData() (line 169 of /srv/www/htdocs/foo.dev/vendor/symfony/http-foundation/JsonResponse.php).
Drupal\Core\Ajax\AjaxResponseAttachmentsProcessor->processAttachments() (Line: 62)
Drupal\Core\EventSubscriber\AjaxResponseSubscriber->onResponse()
call_user_func() (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch() (Line: 191)
Symfony\Component\HttpKernel\HttpKernel->filterResponse() (Line: 179)
Symfony\Component\HttpKernel\HttpKernel->handleRaw() (Line: 80)
Symfony\Component\HttpKernel\HttpKernel->handle() (Line: 58)
Drupal\Core\StackMiddleware\Session->handle() (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle() (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle() (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle() (Line: 23)
Stack\StackedHttpKernel->handle() (Line: 708)
Drupal\Core\DrupalKernel->handle() (Line: 19)
i have a feeling that the difference is that the options form itself is already loaded with ajax but I have no clue how i can solve this or where to find example code