Hello,

I'm looking for an option to reset form values after successful submission. Actually, using javascript is rather straight forward, but was wondering if there was a way with php alone. It seems there would be...

Basically, I've just learned about this key value :

if (!empty($form_state['executed'])) {
  // I could therefore use this in my AJAX callback to reset my form
}

I thought I could use drupal_get_form, but learned otherwise.

I then found a similar issue with ctools 6.x #1025448: Add an AJAX form example to the CTools ajax sample module

It seems that I would have to (re)build the form with the equivalent native 7.x drupal_build_form, but there are obviously differences between the ctools 6.x ajax framework and the new native drupal ajax framework. I've tried a few variations of the above, but it's not working for me.

Any clue would be appreciated.

Cheers

Comments

rfay’s picture

There are no form values after a successful submission in a normal situation, so I'm a little baffled about what you mean.

But a standard technique, used by the core search module, for example, for form submission just to redirect to a GET url and then build the page using the arguments while building the page.

What does this have to do with AJAX though?

rfay’s picture

Oh, you *can* use

$form_state['rebuild'] = TRUE;

in your submit handler, and the form will be still alive. It's a little sketchy for normal form submission, but it will work. You can also set a marker like $form_state['i_submitted_this'] = TRUE in the submit handler.

nlambert’s picture

Thank you for your answer rfay.

I figured this must be the case (answer 1) and found it hard to believe it would be any different.

Now I'm pretty sure I know what the problem is... I used the webform module to quickly whip up a form. I assumed it would be no different, but since I've found hints that it might not.

I'm pretty confident that if I made a form from scratch I wouldn't have this problem. I'll do that and report back.

nlambert’s picture

Well, the fields still stay populated even with a hand made form.

Just to be sure we're on the same page, here's some pseudo code

//hook_menu
function my_module_menu() {
  $items['myform'] = array(
  'title' => 'My Test Form',
  'page callback' => 'drupal_get_form',
  'page arguments' => array('my_form'),
  'access callback' => TRUE,
  );
  return $items;
}
function my_form() {
  $form['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Name'),
    '#required' => TRUE,
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
  );
  $form['submit']['#ajax'] = array(
    'callback' => 'ajax_callback',
    'progress' => array('type' => 'throbber'),
    'effect' => 'fade',
    'wrapper' => 'my-form',
  );    
  $form['#submit'][] = 'my_form_submit';
  return $form;
}
function my_form_submit() {
  drupal_set_message(t('The form has been submitted.'));
}

This is my ajax callback

function ajax_callback($form) {		
  $commands = array();
  $commands[] = ajax_command_prepend(NULL, theme('status_messages')); // Messages output to a Drupal settings variable with registry alter
  $commands[] = ajax_command_append_messages();  // and appended into another area
  $commands[] = ajax_command_replace(NULL, drupal_render($form));
  return array('#type' => 'ajax', '#commands' => $commands);
}

but I also tried the basics

function ajax_callback($form) {		
  return $form;
}

I've also tried without the #ajax key. The fields are cleared after the page refresh.

I've played around with this quite a bit. My original solution was a second custom command - ajax_command_clear_form - which in jq was $('#my-form').clearForm();

My original solution works great, but I guess curiosity got the best of me. Why aren't those form values cleared in the first place?

If you do have any thoughts it would be great to hear

rfay’s picture

I guess the question is "what does populated mean?"

If you're talking about the defaults provided on a form, there are two things.

1. Your browser very much likes to populate these.
2. $form_state['input'] is often used to populate on multistep forms, and $form_state['input'] = array() is sometimes used to clear it.

nlambert’s picture

AH! interesting

ok, so in my ajax callback I did

  dsm($form_state);
  if (!empty($form_state['executed'])) {
    $form_state['input'] = array();
    $form_state['values'] = array(); //tried this also for the heck of it
  }
  dsm($form_state);
  return $form;

So the array(s) get(s) cleared, but I can still see this in the firebug POST (notice value="qsdf") :

<input type="text" id="edit-name--3" name="name" value="qdsf" size="60" maxlength="128" class="form-text required" />

Just for testing, I also put dsm($form_state) in my_submit callback and tried without #ajax. I noticed that $form_state['input'] still has values, but the form is cleared once submitted.

I could do this :

  if (!empty($form_state['executed'])) {
    $form['name']['#value'] = '';
  }

but then I would have to foresee every possible field.

I really appreciate your help. If you need more information for this to be any clearer, please ask.

nlambert’s picture

If there is any lingering doubt concerning my goal, here is a sentence that should sum things up :

What I'm trying to achieve is to have the form work as if it were in an iframe (in the end the form comes up empty)

I've tried a few new things, desperate as they may seem...

if (!empty($form_state['executed'])) {
  $form_state = form_state_defaults();
}

or

if (!empty($form_state['executed'])) {
  $form = ajax_get_form();
}

There are tons of examples that I've looked at, but most people do it something like :

if (!empty($form_state['executed'])) {
  return 'thank you'; // or whatever, but no form
}

OR something similar like the ctools modal login demo.

If anyone has a thought, I'm definitely all ears.

And thanks again rfay for your time.

TheOptimizer’s picture

If I understand you well, you want to reset a field after an AJAX call.
You could try to use ajax_command_invoke in your ajax_callback function. Try to add something like this:

$commands[] = ajax_command_invoke($selector, 'val', array(''));

$selector is then the jQuery selector of the fields you want to reset.

nlambert’s picture

Hello TheOptimizer,

Thank you for your answer.

I've since resorted to a custom $commands[] function that does $(selector).clearForm().

However, I'd expect Drupal to return an empty form after $form_state['executed'] has been applied.

Imagine a form without ajax and no redirect :

  • You fill out the form
  • Click send
  • The page refreshes
  • You're left with an empty/clear form and an "OK" message in $messages

I'd expect the same from an ajax form, but without the page refresh of course.

Cheers

adammalone’s picture

I've run into a similar issue and indeed just decided after a) a while attempting things and b) seeing this thread to go with setting

  $form['name']['#value'] = '';

within the ajax callback. A possible way to mitigate having to input field names manually could be a foreach loop with some kind of code similar to the beneath:

  if (!empty($form_state['executed'])) {
    foreach ($form as $element) {
      if (is_array($element)) {
        if (isset($element['#value'])) {
          $form[$element]['#value'] = '';
        }
      }
    }
  }
  return $form;

This is just an idea off the top of my head and as yet I've not tried it out as I only needed to clear one field but it strikes me as a method that could work.

lmeurs’s picture

Just setting the rebuild variable to FALSE does not return an empty form. Is it expected behavior for Drupal to automatically re-populate through AJAX submitted forms?

Helped by the earlier posts, my solution is:

function mymodule_form_submit($form, &$form_state) {
  $form_state['input'] = array();
  $form_state['rebuild'] = TRUE;
}

Emptying the input array and setting rebuild to TRUE does return an empty form. I also tested it on default field values, these are inserted correctly as well. The submit hook is only called on submission after all validating is done, so an extra check for the value of $form_state['executed'] seems redundant.

eme’s picture

Well, I'm ajaxifying an entity form as well, but do not understand fully how you made it work.

I tried to have a new submit with code above (#11), and with $commands[] = ajax_command_replace(NULL, drupal_render($form)); (or with form ID instead of NULL), and my form is still full of values.

Did I misunderstood your explanations ?

Of course, it works well when emptying the form manually (ex. : $form['title']['#value'] = ''), but with entities, there may be lots of fieds, and of course not always '#value' properties...

Eugene Fidelin’s picture

Solution #11 woks for simple forms.

If you want to clear node form after succefull AJAX request - try to use this solution http://drupal.stackexchange.com/a/36932/7313

eme’s picture

Thanks. I succeeded to do it, and you can see the result for those who are interested you can see the result here : http://drupal.org/sandbox/eme/1594950 (module that ajaxify form entities).

mathankumarc’s picture

In my case If I submit a form using jQuery then the form values are kept maintained

example, I'm using the following snippet to submit the form,

$('.my-form').submit();

and I have one textarea, and the value of that textarea is kept maintained, however it should be cleared.

#11 solved the problem.

One more thing my form is a ajax form, if I submit the form using jQuery then the page is getting reloaded. I think the form is not submitted using ajax.

j0rd’s picture

Title: Reset form values after successful submission » Reset form values after successful ajax submission

Post #11 fixed for me. Thank you.

SGhosh’s picture

Post #4 did the trick for me.

This is my callback function -

function connection_filter_reset($form, &$form_state) {
  $commands[] = ajax_command_replace(NULL, drupal_render($form['ajax_wrapper']));
  $commands[] = ajax_command_invoke('#send-contract-card-form', 'reset_all_filters');
  return array('#type' => 'ajax', '#commands' => $commands);
}

In JS -

// Custom function that will be called in ajax callback for reset form button
$.fn.reset_all_filters = function() {
    // 1. Unselect all select filter options
    // 2. Remove class from plugin btn that is used to change color of label when filter option selected
    // 3. Refresh the select filter plugin
    $(".connection-select-filter-wrapper select option:selected").removeAttr("selected");
    $('.btn.selected-filter').removeClass('selected-filter');
    if (ie_v8) {
        $('label.selected-filter').removeClass('selected-filter');
    } else {
        $('.connection-select-filter-wrapper select').multiselect('refresh');
    }

    // Clear the search input
    $('.form-item-search-connections input').val('');
}



Community rocks! \m/ :)

talgat’s picture

Issue summary: View changes

I solved this problem next way. Check $form_state['executed'] && clear $form['field_name']['#value']

function my_ajax_callback($form, &$form_state) {
	if (!empty($form_state['executed'])) {
		$form['result'] = array(
			'#markup' => 'Done!'</b>',
		);
		$form['name']['#value'] = '';
		$form['email']['#value'] = '';
		return $form;
	} else {
		$form['result'] = array(
			'#markup' => 'Error!'</b>',
		);
	}
	return $form;
}
bartram’s picture

I rebuild the form from the cached form, without the input values set.


function my_ajax_callback($form, &$form_state) {

  if (!form_get_errors()) {

    $form_id = $form['#form_id'];

    // Get the unpopulated form.
    $form = form_get_cache($form_state['input']['form_build_id'], $form_state);

    // Rebuild it, without values
    $form_state['input'] = array();
    $form = form_builder($form_id, $form, $form_state);

  }
  return $form;

}

Anonymous’s picture

bartram,

thank you! i've spent ton of time in tries to resolve this issue. and here you go. thanks!

sneha_surve’s picture

Solution #11 woks for simple forms.

In submit handler you need to set
$form_state['input'] = array();

It works! :D

PrzemyslawKot’s picture

For Drupal 8.

You can't remove all data in $form_state['input'](nor treat it like array). You have to leave id's of form and form build.
You do this like this:

        $userInput = $form_state->getUserInput();
        $keys = $form_state->getCleanValueKeys();
        $newInputArray = [];
        foreach ($keys as $key) {
            if ($key == "op")  continue;
            $newInputArray[$key] = $userInput[$key];
        }

        $form_state->setUserInput($newInputArray);
        $form_state->setRebuild(true);
satishb’s picture

$commands[] = ajax_command_invoke('#edit-comments', 'val', array(''));

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

worked for me ,#edit-comments is the HTML id of the field i wanted to replace