I am attempting to use ajax api on a form
my code sample has 2 ajax calls in, the problem is with the $form['one'] call (the other one is fine)
The problem is that it runs once and only once (without a full page reload)
I have checked the code with xdebug suring the first ajax call and everything seams to be in order.
The form is initially generated with hook_menu using drupal_get_form()
What is going wrong here?
------------------------------------
// My form array
function ajax_play_simplest($form, &$form_state) {
$form = array();
$form['changethis'] = array(
'#type' => 'select',
'#options' => array(
'one' => 'one',
'two' => 'two',
'three' => 'three',
),
'#ajax' => array(
'callback' => 'ajax_play_example_simplest_callback',
'wrapper' => 'replace_textfield_div',
),
);
// This entire form element will be replaced with an updated value.
$form['replace_textfield'] = array(
'#type' => 'textfield',
'#title' => t("The default value will be changed"),
'#value' => t('the default valoo'),
'#description' => t("This will change"),
'#prefix' => '
'#suffix' => '
'
);
$form['one'] = array (
'#type' => 'textarea',
'#cols' => 2,
'#title' => t('textarea one'),
'#description' => t('this will show the content of the text box'),
'#ajax' => array(
'callback' => 'callback_one',
'wrapper' => 'textarea_one',
),
'#prefix' => '
'#suffix' => '
'
);
return $form;
}
//the ajax callback
function callback_one($form, $form_state){
$form['one'] = array(
'#type' => 'textarea',
'#cols' => 5,
'#title' => t('textarea one'),
'#description' => (!empty($form_state['values']['one'])
? $form_state['values']['one'] : t("Not changed yet")) . "'",
'#ajax' => array(
'callback' => 'callback_one',
'wrapper' => 'textarea_one',
),
'#prefix' => '
'#suffix' => '
'
);
return $form['one'];
}
Comments
All changes to the form must
All changes to the form must be made in the form function. The ajax function should not change anything, its job is to return the form element(s) that are being changed or inserted.
In the case what do i do if i
In the case what do i do if i want to modify a form in response to user actions
for example I may have a countries field and a counties/states/regions field and i may want the list of counties/states/regions to change when the user selects a different country.
This is quite common functionality and a very typical example of AJAX use.
Would I need to re-call the hook_form function from the ajax function and code the hook_form function in such a way that it builds the form differently depending on if it is being called on the initial page load or if ajax has called it? if yes.....
Would i need to re-build the whole form each time or just the object which should change?
and
can hook form accept any extra parameters - which i would use to pass in a variable which determines where it is being called from and what should change?
The form is already
The form is already automatically rebuilt every time. This is what happens on a normal non-ajax form submission with Drupal:
1) The form is built
2) All _form_alter() functions alter the form
3) The php array representation of the form is cached in the database
4) The form is sent to the browser
5) The user submits the form
6) The submitted values are compared with the cached form, to check if the submitted values could have been submitted from that form. If they are, the form submission is allowed.
This is what happens when you include AJAX into the mix. The start and end are the same, but there is more in the middle:
1) The form is built
2) All _form_alter() functions alter the form
3) The php array representation of the form is cached in the database
4) The form is sent to the browser
5) User makes change that causes some ajax.
6) The values are sent to the server in a background call using JavaScript
7) The submitted values are checked against the database to see if the submitted values are valid
8) If the are, the form is rebuilt, passing $form_state['values'] to the form rebuild
9) All _form_alter() functions are called
10) The new form is cached in the database, replacing the old one
11) The form is sent to the AJAX callback function
12) The AJAX callback function determines which parts of the form are to be sent back to the browser
13) The new parts are sent back to the browser
14) The browser inserts them into the form
15) The user submits the form
16) The submitted values are compared with the cached form, to check if the submitted values could have been submitted from that form. If they are, the form submission is allowed.
As you can see, in step 10, the form is cached, and the ajax callback function is called after that. This is why changes need to be made in the form definition, and not in the ajax callback.
So- taking my example of a
So- taking my example of a region/state/county field which gets a new list of values when the country field changes - would I be correct to believe that I put something like the following in the hook_form function
if (!isset($form_state['countries']))
{
regions['value'] = some default
}
else
{
some logic which fetches a list of regions for the selected country
regions['value'] = list of regions in that country
}
The TRUE IF condition runs when the page is made
The ELSE IF condition would run if an AJAX call has been made, and the region value has been changed.
if this is correct
What,if any, code would i need to place in the ajax function?
You've got the right idea,
You've got the right idea, but you want $form_state['values']['countries'].
You need to return the relevant code from your AJAX callback.
yay, i got it working
yay, i got it working
there is still a bit of confusion
I have the following setup (only relevant code is shown)
When the page first loads hook_menu calls main_page() which uses drupal_get_form() to create the form properly
drupal_get_form() is not called from the ajax callback so how is the form being rendered properly?
In addition here is the full code (in case i was mistaken about what is relevant here)
Can you please edit your post
Can you please edit your post and wrap your code in <?php ?> tags to make it more readable? I'll look at your code after that.
Thank you.
done.
done.
When the page first loads
The ajax callback processes the form (which happens on the initial page generation inside drupal_get_form()), then passes the generated form to your ajax callback. This is why you don't call drupal_get_form() inside the ajax callback - by the time the ajax callback function is called, all of the form processing has been completed. Think of it as if the system called drupal_get_form() for you already.
would a a stack trace placed
would a a stack trace placed inside the ajax callback reveal that the drupal_get_form() function has in fact been called prior to the ajax callback?
No, because it's not called
No, because it's not called in ajax processes. I believe drupal_process_form() is called if I remember correctly. This is also called within drupal_get_form(). Although whether this will show up in the stack in the ajax callback is questionable - the entire process may be completed before the ajax callback is called, and if so, wouldn't show up in the stack.