0

Ok, I have a page where are the following items:

  • A select with the list of nodes
  • An edit form for the selected node
  • A display of the selected node

When the select changes I want the form to be updated (in order to allow the edition of this node) and the display to change.

For the two first elements, I load the edit form and add my select at the top and then

$form['selection_list']['#ajax'] = array(
  'callback' => 'MYMODULE_ajax_callback',
  'wrapper' => 'selection_form'
);

in MYMODULE_ajax_callback, I use ajax commands, one to update the display of the node (it works like a charm), and another to update the form itself. To update the form, I use

$form_state['build_info']['args'] = array($selected_node);
$form_state['rebuild'] = TRUE;

and then call

$form = drupal_rebuild_form('selection_node_form', $form_state, $form);

The form is reloaded but its content won't change. If I add a #markup in my form with the $selected_node->nid, I can see the new value everytime I select another node, but the fields of the form are not changed. For instance, I can still see the title of the first edited node.

**

EDIT: full code (irrelevant code is replaced by a capital comment)

/**
 * This function is used for the first creation of the form (static)
 * and its update (ajax)
 */
function MYMODULE_get_edit_form($selection, $old_form = NULL, $form_state = NULL) {
  drupal_add_library('system', 'drupal.ajax');
  drupal_add_library('system', 'drupal.form');

  if (is_null($form_state)) {
    $form_state = form_state_defaults();
  }
  $form_state['build_info']['args'] = array($selection);
  form_load_include($form_state, 'inc', 'node', 'node.pages');
  if ($form_state['rebuild'] == TRUE) {
    $form = drupal_rebuild_form('selection_node_form', $form_state, $old_form);
  } else {
    $form = drupal_build_form('selection_node_form', $form_state);
  }

  $form[] = array('debug' => array('#type'=>'markup', '#markup'=>$selection->title));

  return $form;
}

/**
 * Here we only clean Drupal's edit form, add some ajax mojo to the submit button and add the node select list
 */
function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'selection_node_form' && !path_is_admin(current_path())) {
    $form['selection_list'] = array('#type' => 'select', '#title' =>'Active mood board', '#weight' => -100);

    /*GENERATE THE LIST AND ENSURE THE CORRECT NODE (STORED IN CURRENT USER) IS SELECTED*/
    $form['selection_list']['#ajax'] = array(
      'callback' => 'MYMODULE_ajax_callback',
      'wrapper' => 'selection_form',
      'method' => 'replace',
      'effect' => 'fade'
    );

    $form['field_models']['#attributes']['class'][] = 'hidden';
    $form['additional_settings']['#access'] = FALSE;
    $form['revision_information']['#access'] = FALSE;
    $form['author']['#access'] = FALSE;
    $form['options']['#access'] = FALSE;
    $form['actions']['preview']['#access'] = FALSE;

    $form['actions']['submit'] = array(
      '#type' => 'button',
      '#value' => 'Update',
      '#limit_validation_errors' => array(),
      '#ajax' => array(
        'callback' => 'MYMODULE_ajax_callback',
        'wrapper' => 'selection_form'
      ),
    );
  }
}

function MYMODULE_ajax_callback($form, $form_state) {
  $commands = array();
  $nid = $form_state['input']['selection_list'];
  global $user;

  $form_renderable = "";
  $form_state['rebuild'] = TRUE;

  $selection = entity_load_single('node', $nid);

  if ($selection->type == "selection" && $selection->uid == $user->uid) {
    //save current selection
    $user_wrapper = entity_metadata_wrapper('user', $user);
    $user_wrapper->field_current_selection->set($nid);
    $user_wrapper->save();

    $form_renderable = MYMODULE_get_edit_form($selection, $form, $form_state);

    /*GENERATE $node_display, $nItems*/

  }

  $commands[] = ajax_command_html('.userMenu a.cartIcon', $nItems);
  $commands[] = ajax_command_replace('.collection > ul', $node_display);
  $commands[] = ajax_command_html('#selection_form', render($form_renderable));
  $commands[] = ajax_command_invoke(NULL, 'windowResize');

  return array(
    '#type' => 'ajax',
    '#commands' => $commands,
  );
}

** EDIT: try without build or rebuild

I first tried to start over with drupal_build_form every time, but the previous values were still there. So I dissected drupal_build_form and removed everything that looked like cache, I replace the call to drupal_build_form with:

 $form = drupal_retrieve_form('selection_node_form', $form_state);
 drupal_prepare_form('selection_node_form', $form, $form_state);
 drupal_process_form('selection_node_form', $form, $form_state);

It works for the first display of a form, then for the first refresh with another selected node, but if I come back to the first node, I get a PDOException "MySQL server has gone away" in the ajax response.

  • I think that would be more helpful if you post the whole code, not just some bits – GwenM Jan 21 '16 at 13:55
  • There, I added almost all the code. – Kodiak Jan 21 '16 at 14:07
  • I'm not really sure, but it might be reloading the same values because the form is cached and the rebuild put them back. – GwenM Jan 21 '16 at 15:49
  • I had the same idea but setting $form_state['cache'] to false won't change a thing. Furthermore, using only drupal_build_form or clearing the form_state leads to the same result. – Kodiak Jan 21 '16 at 16:04
  • When you add a dsm($form_state) on the top of your selection_node_form with the cache disabled, what does it say? – GwenM Jan 21 '16 at 16:29

Your Answer

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

Browse other questions tagged or ask your own question.