I'm having some trouble with using #ajax in hook_form_alter.
Is it possible to use #ajax with custom fields created in hook_form_alter?
After clicking the button $form['taxonomy_submit_' . $vid], there's nothing in $form_state['values'] but the button info. See code below.
Any help would be appreciated

function my_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'foobar_node_form') {
    // taxononmy_reference select field
    $field = 'field_' . $name;
    $form[$field]['#prefix'] = '<div id="tax-select-' . $vid .'">';
    $form[$field]['#suffix'] = '</div>';

    $form['tax_form'] = array(
      '#prefix' => '<div id="tax-form">',
      '#suffix' => '</div>',
    );

    // Add Term button
    $form[$field . '_submit'] = array(
      '#type' => 'button',
      '#value' => t('Add term'),
      '#name' => 'addform_' . $vid,
      '#limit_validation_errors' => array(),
      '#ajax' => array(
        'wrapper' => 'tax-form',
        'callback' => 'my_addterm_form',
      ),  
    );

    // Fields to Add Term added through 'neams_addterm_form' callback
    // These fields are added succesfully
    if (isset($form_state['triggering_element']['#name']) && ($form_state['triggering_element']['#name'] == 'addform_' . $vid)) {
      // Add term fields
      $form['term_' . $vid] = array(
        '#title' => t('Add term to %machine_name', array('%machine_name' => $name)),
        '#type' => 'fieldset',
        '#weight' => 10,
      );
      $form['term_' . $vid]['term_name_' . $vid] = array(
        '#type' => 'textfield',
        '#title' => t('Name'),
        '#required' => TRUE,
      );

      // ... Omitting other fields for example simplification

      // Button not seeming to submit the value of $field['term_name' . $vid]
      // See next IF statement
      $form['term_' . $vid]['taxonomy_submit_' . $vid] = array(
        '#type' => 'button',
        '#name' => 'add_me',
        '#value' => t('Add Term'),
        '#submit' => array('neams_addterm_term_form_submit'),
        '#limit_validation_errors' => array(),
        '#ajax' => array(
          'callback' => 'my_addterm_addterm_js',
          'wrapper' => 'tax-select-' . $vid,
        ),
      );
    }
    // This condition fails 
    if (isset($form_state['triggering_element']['#name']) && ($form_state['triggering_element']['#name'] == 'add_me')) {
      watchdog('my_addterm', 'add_me button has been clicked', array(), WATCHDOG_DEBUG);
      ... 
    }       
  }
}

/**
 * Load Add term fields on node form
 */
function my_addterm_form($form, $form_state) {
  // not being specific with return form value for example
  return $form;
}

/**
 * "Add term" ajax callback
 */
function my_addterm_addterm_js($form, $form_state) {
  // Following watchdog message returns:
  // Array
  // (
  //    [taxonomy_submit_2] => Add Term
  //    [2] => Add Term
  // )
  watchdog('my addterm', '$form_state['values'] on add term submit callback: <pre>%form_state</pre>', array('%form_state' => print_r($form_state['values'], true)), WATCHDOG_DEBUG);
  // not being specific with return form value for example
  return $form;
}

Comments

nevets’s picture

First it would help if you stated what you want to achieve (what it the purpose of the code)

Some things noticed

Early on you have $field = 'field_' . $name; but $name is not set

In the same vein, $vid is used without being set

The button elements may need '#executes_submit_callback' => FALSE,

Reading between the lines, it looks like are trying to add terms on a node form one by one, which would be an alternative way to add taxonomy terms and if this is correct I would think implementing hook_field_widget_info() to provide an additional widget would make more sense than hook_form_alter().

There are a lot of form elements that I am not clear on their purpose, I would have been tempted to get rid of the buttons and attach the ajax to $form['term_' . $vid]['term_name_' . $vid] = array(

stongo’s picture

Sorry for some of the holes in the code I pasted. There's a lot more code I left out to simplify the example. $vid and $name are actually set in a foreach to account for multiple taxonomy_reference fields, and there's more fields that get ajaxed in to add a term (replicates term add form).
You are correct that I am trying to add the capability of adding a new taxonomy term to the parent vocabulary of taxonomy_references on the node form.
Pressing first ajax button returns the correct $form_state['values'] but then as mentioned, the fields that get ajaxed in don't appear in $form_state['values'] nor any of the other fields when the new button gets pressed.
hook_field_widget_info() might actually be what I'm looking for. I'm not familiar with widgets in the field api, so will definitely look in to it.
I really appreciate your time, and thanks for helping :)

nevets’s picture

Ok, I see the problem, its because you are building the form wrong. All the code inside

    if (isset($form_state['triggering_element']['#name']) && ($form_state['triggering_element']['#name'] == 'addform_' . $vid)) {
    ...;
    }

will not work as you want because the elements inside the if are conditional on a transitional event so when the "Add me" button is pressed, the test fails and the elements are not added. (Forms are rebuilt on submission including ajax submissions). A possible quick fix would be to change the existing 'if' to

if ((...existing test) || !empty($form_state['values'][['term_name_' . $vid])) {
stongo’s picture

Thanks again for taking the time to help me. I was still having some trouble, so ended up loading the taxonomy term entry form in a ctools modal window , and then used #ajax to refresh the select list once the modal form was submitted.
I will be posting this module soon as a sandbox project, so let me know if you're interested in checking it out.