5

I have a node form in a block, that is submitted using AJAX.

I've created my own callback, because I'm adding the created node to the page if the submission was successful.

Now, I want to reset the node form to the default values. Any ideas on how to accomplish that?

Update: I've managed to replace the form, by looking at the way node_add() works.

$new_node = (object) array(
  'uid' => $user->uid,
  'name' => (isset($user->name) ? $user->name : ''),
  'type' => 'node_type',
  'language' => LANGUAGE_NONE,
);

And then, I'm replacing the entire form with the return value from drupal_render(drupal_get_form('node_form', $new_node));

The form gets replaced as it should be, apart from some ids being different. However, when I submit the new form, I'll get a javascript alert window, with the entire contents of a new page. I can see from the HTML, that it's the page for the node that has been created. I suppose the AJAX callback gets redirected to the new node, but I don't know why.

Any clues?

4 Answers 4

7

Got it!

The main problem was that the new form was loaded from a cached version of the previous submitted form.

This is what I've got in my AJAX callback:

$new_form_state = array();
$new_form_state['build_info']['args'][] = (object) array(
  'uid' => $user->uid,
  'name' => (isset($user->name) ? $user->name : ''),
  'type' => 'node_type',
  'language' => LANGUAGE_NONE,
);
$new_form_state['no_redirect'] = TRUE;
$new_form_state['input'] = array();
$new_form = drupal_build_form('node_type_node_form', $new_form_state);
$commands[] = ajax_command_replace('#node-type-node-form', drupal_render($new_form));

The $new_form_state['no_redirect'] = TRUE; prevents the redirect, and the empty array in $new_form_state['input'] prevents the form from being loaded from a cached version.

@googletorp, thanks for the help!

2
  • How would you actually set a value of a field in that form when it reloads?
    – revolt
    Commented Feb 13, 2012 at 23:45
  • Do you mean a default value? I guess that would work by simply setting a default value in the field configuration. Commented Mar 12, 2012 at 7:08
3

If you are are using Drupal 7 you can unset form_state['values'] and rebuild the form which should work (untested).

An alternative solution would be to issue ajax commands and update the form with the default values fetched from the form definition.

3
  • Couldn't get the first suggestion to work, even though I reinitiated form_state with default values from form_state_defaults(). As for the second suggestion, how do I retrieve the default values? My first approach was to build the form using node_add(), but then I'm getting "Cannot unset string offsets in <path>/<root>/modules/field/field.default.inc on line 41". However, this still seems like the best approach, if I could get it working... Commented Jun 3, 2011 at 12:05
  • @Olof You should have the form in your ajax callback (D7)
    – googletorp
    Commented Jun 3, 2011 at 13:08
  • 1
    I've figured out how to retrieve the default values for each field. However, the structure of this seems to differ depending on the field, and it could get complicated to implement this in a somewhat dynamic way. So your first suggestion still seems like the better one. I'll dig deeper into it to find a solution.. Commented Jun 7, 2011 at 7:11
2

I have the same task. Node add form must be posted via AJAX. After node is successfully created - form must be ready to add next node (i.e. all form fields must be empty). If form is not validated - it must be shown to user again to allow him fix errors.

This is my solution

function MY_MODULE_form_CONTENT_TYPE_node_form_alter(&$form, &$form_state, $form_id) {

  $form['actions']['submit']['#ajax'] = array(
    'wrapper' => $form_state['node']->type . '-node-form',
    'callback' => 'MY_MODULE_node_add_callback',
    'method' => 'replace',
    'effect' => 'fade',
  );

  // We can have several forms on one page.
  // This id must be unique, because ajax behavior is attached using it.
  $form['actions']['submit']['#id'] = 'edit-submit-' . $form_state['node']->type . '-ajax';
}

function MY_MODULE_node_add_callback($form, &$form_state) {

  $node = $form_state['node'];

  if (!empty($node->nid)) {

    // Node is created successfully.
    // Return the same from but with empty fields.
    $new_node = (object) array(
      'uid' => $node->uid,
      'name' => $node->name,
      'type' => $node->type,
      'language' => $node->language,
    );

    $new_form_state = array();
    $new_form_state['build_info']['args'] = array($new_node);
    $new_form_state['values'] = array();
    $new_form_state['method'] = $form_state['method'];

    form_load_include($new_form_state, 'inc', 'node', 'node.pages');

    return drupal_rebuild_form($node->type . '_node_form', $new_form_state);
  }
  else {

    // Node is not created because of validation fail.
    // Return current form so user can continue editing and fix errors.
    return $form;
  }
}
2
  • Hi i am using this code to rebuild the node form. Can you please explain 'Argument 1 passed to drupal_array_set_nested_value() must be an array' ERROR.
    – Sibiraj PR
    Commented Feb 28, 2013 at 6:58
  • @Eugene, thx for the answer. Do you know how to do it in d8? I have tried $form = \Drupal::formBuilder()->rebuildForm($this->getFormId(), $form_state) but no luck. I am alsotruing to do $form_state->setRebuild(TRUE);, $form_state->setValues([]); in th fosm submit and ajax callback.
    – milkovsky
    Commented Nov 11, 2016 at 14:45
0

Use drupal_rebuild_form() function. http://api.drupal.org/api/drupal/includes%21form.inc/function/drupal_rebuild_form/7

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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