What is the way to trigger a Drupal form via JavaScript, and pass new values to $form_state
while doing so?
I have a main form, which has an element that triggers a jQuery UI dialog with a form in it. When submitting the dialog form, I want to bring the values back into $form_state
. I want the main form to display and save the values from both forms. Both Ctools Ajax example and MonoDialog show examples that just manipulate the DOM of the main page/form after submitting a form in a dialog.
One thing I could maybe do is populate a hidden form field with the values from the dialog form in JSON format, and then trigger an ajax button with jQuery. I rather not do this as it doesn’t sound like a clean solution.
What I try to achieve is kind of like the views ui interface, which has a form with form in dialogs. Submitting the dialog forms, updates the main form.
Code example
<?php function example_main_form($form, &$form_state) { // The main form is defined here. Includes a button which triggers a // callback function (example_main_form_callback) to open up a new form // in a dialog popup. Upon this ajax trigger, it also populates $form_state // with some values to pass to the dialog form. } function example_main_form_callback($form, &$form_state) { $commands = array(); // open dialog $commands[] = ajax_command_invoke('#dialog', 'dialog', array('open')); // dialog title $title = t('Configure:') . ' ' . $form_state['dialog']['values']['title']; $commands[] = ajax_command_invoke('#dialog-title', 'html', array($title)); // dialog body $body = drupal_render(drupal_get_form('example_dialog_form', $form_state['dialog'])); $commands[] = ajax_command_invoke('#dialog-body', 'html', array($body)); return array('#type' => 'ajax', '#commands' => $commands); } function example_dialog_form($form, &$form_state) { // include this file in build_info form_load_include($form_state, 'inc', 'example', 'example.forms'); // The popup dialog form is defined here. // the submit button has an ajax callback, which calls // example_dialog_form_callback below. } function example_dialog_form_callback($form, &$form_state) { // This callback closes the dialog, but I also want to populate the // form_state of the main form with the values of this saved form. The values // are available in this callback's $form_state, but I'm not sure what the // best way is to pass them on to the main form. Is it possible to trigger // another form programmatically using jQuery? $commands = array(); // close dialog $commands[] = ajax_command_invoke('#dialog', 'dialog', array('close')); return array('#type' => 'ajax', '#commands' => $commands); }
I think I could attach the dialog form values to the Drupal.ajax.example_element.options.data
object. In this way, when the main form is programmatically triggered for an Ajax callback, the values in options.data
will be added to the main form $form_state['input']
. That’s the cleanest approach I found so far, but still not straightforward. A separate function is required to populate options.data
. One options is to extend options.beforeSerialize()
, but in my case the Ajax element is dynamic. (See How to extend or "hook" Drupal Form AJAX?) Thus this approach would work better:
In the dialog form callback:
<?php function example_dialog_form_callback($form, &$form_state) { $dialog_id = 'dialog-id'; $commands = array(); // close dialog $commands[] = ajax_command_invoke('#dialog', 'dialog', array('close')); // Call function which attaches the dialog form values to Drupal.ajax.{dialog-id}.options.data. // After triggering the dialog ajax callback, the dialog values will be added to the $form_state of // the main form $data = array( 'id' => $dialog_id, 'values' => $form_state['input'], // for example, but could be cleaned up. ); $commands[] = ajax_command_invoke(NULL, 'dialogValues', array($data)); // trigger dialog button $commands[] = ajax_command_invoke('#' . $dialog_id, 'trigger', array('click')); return array('#type' => 'ajax', '#commands' => $commands); }
The jQuery function:
$.fn.dialogValues = function(data) { // dialog ajax id var dialogAjaxId = data.id; // add values as JSON, so we can pass multi dimensional arrays Drupal.ajax[dialogAjaxId].options.data._dialog_values = JSON.stringify(data.values); };
Is there a better solution?