Related to my previous question, but this specifically pertains to how ajax works rather than what $form_state
does.
I have a form class defined with the following code (an "instruction" in this code is just the name for a blank text field, and there needs to be the ability to add as many of these text fields as the user desires):
namespace Drupal\mymodule\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
class MymoduleSubmitForm extends FormBase {
/**
* {@inheritdoc}
*/
public function getFormId() {
// Unique ID of the form.
return 'mymodule_submit_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
// Create a $form API array.
$form['#tree'] = TRUE;
$i = 0;
$num_instructions = $form_state->get('num_instructions');
if (empty($num_instructions)) {
$num_instructions = $form_state->set('num_instructions', 1);
$num_instructions = $form_state->get('num_instructions');
}
$form['instructions'] = array(
'#type' => 'fieldset',
'#title' => 'Instructions',
'#prefix' => '<div id="instructions-wrapper">',
'#suffix' => '</div>'
);
for ($i = 0; $i < $num_instructions; $i++) {
$form['instructions'][$i] = [
'#type' => 'textfield',
'#title' => $this->t('@num', ['@num' => $i + 1]),
];
}
$form['add_instruction'] = array(
'#type' => 'submit',
'#value' => $this->t('Add step'),
'#ajax' => array(
'callback' => '::addInstructionCallback',
'wrapper' => 'instructions-wrapper'
),
);
$form_state->setCached(FALSE);
$form['submit'] = array(
'#type' => 'submit',
'#value' => $this->t('Submit')
);
return $form;
}
/**
* Implements callback for Ajax event
*
* @param array $form
* From render array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* Current state of form.
*
* @return array
* Form fields.
*/
public function addInstructionCallback(array &$form, FormStateInterface $form_state) {
ddl($form);
$name_field = $form_state->get('num_instructions');
return $form['instructions'];
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
ddl(1); //ignore this for now
}
The form is called in mymodule.module
like this:
function mymodule_node_view_alter(array &$build, Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display) {
$current_path = \Drupal::request()->getRequestUri();
$paths = explode('/', $current_path);
if ($paths[1] == 'submit-set')
$build['myform'] = \Drupal::formBuilder()->getForm('Drupal\mymodule\Form\MymoduleSubmitForm');
}
My problem is that my Ajax callback function addInstructionCallback
does not seem to be firing at all. The indicator appears when I click the button to show that the ajax function is doing its work, and then it goes away and the form hasn't changed. I check /admin/reports/debug and it is completely empty, the ddl($form);
call from within my callback function has not fired. There are no PHP error messages to be found in reports or log files either.
I am mostly following the code in this example, but I have also tried an approach using AjaxResponse
like in this example and it hasn't made a difference. I have also tried changing the button to a checkbox in case it was breaking because of my unfinished submit function, but that didn't make a difference either.
What am I doing wrong with Ajax?
Update: Console is doing some weird stuff:
Uncaught AjaxError:
An AJAX HTTP error occurred.
HTTP Result Code: 200
Debugging information follows.
Path: /submit-set?ajax_form=1
StatusText: OK
ResponseText:
(entire contents of my page, including theme headers and footers, followed by
{"ajaxPageState":{"theme":"bartik","libraries":"admin_toolbar\/toolbar.tree,admin_toolbar\/toolbar.tree,admin_toolbar_tools\/toolbar.icon,admin_toolbar_tools\/toolbar.icon,bartik\/global-styling,bartik\/global-styling,bartik\/messages,classy\/base,classy\/base,classy\/messages,classy\/messages,classy\/node,classy\/node,contextual\/drupal.contextual-links,contextual\/drupal.contextual-links,contextual\/drupal.contextual-toolbar,contextual\/drupal.contextual-toolbar,core\/drupal.active-link,core\/drupal.active-link,core\/html5shiv,core\/html5shiv,core\/normalize,core\/normalize,history\/mark-as-read,history\/mark-as-read,quickedit\/quickedit.inPlaceEditor.plainText,shortcut\/drupal.shortcut,shortcut\/drupal.shortcut,system\/base,system\/base,toolbar\/toolbar,toolbar\/toolbar,toolbar\/toolbar.escapeAdmin,toolbar\/toolbar.escapeAdmin,tour\/tour,tour\/tour,user\/drupal.user.icons,user\/drupal.user.icons"},"ajaxTrustedUrl":{"\/search\/node":true},"history":{"nodesToMarkAsRead":{"45":true}},"toolbar":{"breakpoints":{"toolbar.narrow":"only screen and (min-width: 16.5em)","toolbar.standard":"only screen and (min-width: 38.125em)","toolbar.wide":"only screen and (min-width: 61em)"},"subtreesHash":"Y9yCNrSN2LUELxt5wnz-3xSDjtgka559ps7ynAoGrpw"},"path":{"baseUrl":"\/","pathPrefix":"","currentPath":"node\/45","currentPathIsAdmin":false,"isFront":false,"currentLanguage":"en","currentQuery":{"_wrapper_format":"html","ajax_form":"1"}},"pluralDelimiter":"\u0003","user":{"uid":"1","permissionsHash":"d0f6778fd5e1fddf0d1d92a309af30862905f78390534ce1aa8a064cbc51b24e"}}
)
Trace:
Drupal.Ajax.error @ {cache}:2995
complete @ {cache}.js:2540
t.complete @ {cache}.js:1320
j @ {cache}.js:2
fireWith @ {cache}.js:2
x @ {cache}.js:4
(anonymous function) @ {cache}.js:4
Have already tried clearing cache.
Update: Modified code to match another example. Still getting the same error.
Update: Adding a console.log(status);
to the called complete
function above return ajax.error(xmlhttprequest, ajax.url);
returns the string parsererror
. Trying to log anything else related to the ajax request to console (such as the xmlhttprequest
parameter) crashes the page.