6

I have an AJAX form. I want to update the text of a textfield when a button is triggered. But this does not work. My form is below:

<?php
function my_form($form, &$form_state) {
  $form['ask_first_name'] = array(
    '#type' => 'textfield',
    '#title' => t('Ask me my first name'),
    '#default_value' => 'I LOVE chickens',
    '#prefix' => '<div id="textfields">',
    '#suffix' => '</div>',
  );
  $form['update'] = array(
    '#type' => 'button',
    '#value' => t('Update'),
    '#ajax' => array(
      'callback' => 'ajax_example_autotextfields_callback',
      'wrapper' => 'textfields',
      'effect' => 'fade',
    ),
  );

  // shouldn't this update the default value when the button is pressed??
  if (isset($form_state['values'])) {
    $form['ask_first_name']['#default_value'] = 'I HATE chickens';
  }

  return $form;
}
?>

When I press the 'update' button I'm expecting the field text to change, but it doesn't. If I use #value instead of #default_value it works, but I know I shouldn't use that because I still want the user to be able to change it again.

<?php
// using #value works - but should I use that?
$form['ask_first_name']['#value'] = 'I HATE chickens';
?>

What is the recommended Drupal way to change the field value after AJAX is triggered?

NOTE: This answer solved the problem in my case, but as mentioned in the comments there is not access to the values in $form_state['values'] after submit. However, I'm storing the data in $form_state['storage'] so I can still access the data, though I'll probably implement ctools object cache in the end.

3

This is taken from the description of #default_value in the form api documentation:

The value of the form element that will be displayed or selected initially if the form has not been submitted yet

Because your form has been submitted, it wont be using #default_value. Just use #value, the user will still be able to change it.

  • 2
    User-entered value will not be includes in $form_state['values'] if #value is set. – AyeshK Feb 5 '13 at 2:51
  • 1
    @Ayesh K. If it works with #value and it's okay to do so, I'll do that. I can always get the value from $form_state['input']? – Web Assistant Feb 5 '13 at 9:06
  • Ayesh K may be correct, I haven't tried it. @ Web Assistant, try it an tell us if it works. – 2pha Feb 5 '13 at 12:33
  • 1
    I've got this working, but the thing stopping me giving it a correct answer is that the data does not appear in $form_state['values'] or $form_state['input'] after submit, as Ayesh said. I've worked around this by storing the data in $form_state['storage']. If I don't find a better answer I'll mark this as the accepted answer. – Web Assistant Feb 5 '13 at 14:30
2

I made it the quick and dirty way. In my ajax callback, I set the

$form['inputfield']['#value'] = $form['inputfield']['#default_value'];

The I changed the value in the input field manually to test if the value can be changed by user and is then submitted. After checking the $form_state['values']['inputfield'] I realized, that the value was correctly submitted, although the field got a '#value' attribute in the ajax callback.

But I think you have to be careful: Only set the '#value' attribute in the ajax callback, not in the form declaration!

Hope that helps, although a little bit late.

  • The extra important part of this is: "you have to be careful: Only set the '#value' attribute in the ajax callback, not in the form declaration!" – DrCord Sep 17 '14 at 20:14
2

As 2pha pointed out #default_value cannot be changed once the form has been submitted. However the array in $form_state['input'] can be manipulated at any time.

To update the example you gave:

if (isset($form_state['values'])) {
  $form_state['input']['ask_first_name'] = 'I HATE chickens';
}

When the actual html for your form is built the value we set in $form_state['input'] will be used as the default value.

  • This seems like the best solution to me – argiepiano Dec 12 '16 at 16:43
1

2pha's answer did not work for me - if I set values with um, value, ie $form['myfield']['#value'] then sure the value changed - but it then ignored further user input!

So this is how I achieved setting values dynamically in my form builder function during ajax call backs and still let the user amend the values (within the if at end).

Note in my case, I'm updating 3 fields whenever the user changes a couple of other fields.

 $form['ld']['letterdrop_allocations'] += array(                                              
     '#type' => 'textfield',                                                                  
     '#title' => t('Letterdrop allocations for %contact in drop %letterdrop',     
       $tokens),                                                                              
     '#description' => 'blah.'                                  
     );                                                                                       

 $form['ld']['letterdrop_notes'] = array(                                                     
     '#type' => 'textfield',                                                                  
     '#title' => 'Notes',                                                                     
     '#description' => t('notes for all allocations %contact in drop %letterdrop',            
       $tokens));                                                                                 

 $form['ld']['letterdrop_kitstate'] = array(                                                  
     '#type' => 'select',                                                                     
     '#title' => 'Kit state',                                                                 
     '#options' => AgcLetterDrop::kitstates(),                                                
     '#description' => 'some words for here');                                                                                                     

 if ($letterdrop_allocations_changed) { // overwrite field values                                         
   unset($form_state['input']['letterdrop_allocations']);                                     
   unset($form_state['input']['letterdrop_notes']);                                           
   unset($form_state['input']['letterdrop_kitstate']);                                        

   $form['ld']['letterdrop_notes']['#default_value'] =                                        
     $ldallocations['notes'];                                                                 
   $form['ld']['letterdrop_allocations']['#default_value'] =                                  
     $ldallocations['lda_id'];                                                                
   $form['ld']['letterdrop_kitstate']['#default_value'] =                                     
     $ldallocations['kit_state'];                                                             

 }                                                                                            

hope that helps - i've lost about ten hours on this!

  • 3
    This will work - the values will change, however it would be simpler to just update $form_state['input'] directly instead of unsetting it and then setting the #default_value – Felix Eve Jun 11 '15 at 6:47
0

I believe the proper way to change the user input or a submitted form value is by calling form_set_value.

This comment explains how to use this.

// form_set_value requires that #parents be set on the field
$form['field_your_field']['#parents'] = array('field_your_field'); 
// set the value by calling form_set_value($element, $value, $form_state)
form_set_value($form['field_your_field'], array('und' => array(0 => array('value' => 'WORKS'))), $form_state);

$form_state is passed by reference so the actual user input is changed and this will be reflected when the form is rebuilt and passed back by ajax callback. Therefore I think it's best to call this function during a form_validate function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.