Hi there,
need some help with a cancel button.
I like to add cancel button to node/add form. the problem are the required fields. Could some one give me an hint, how to solve this?

Cheers

Comments

barrett’s picture

When you say "the problem are the required fields", do you mean that clicking the cancel button gives an error if the required fields are not filled?

What I've done with similar cases where I needed a Back button is put a bit into the top of the form validation function that that tests if the Back button was pushed and if so clears out the validation errors thrown by core validation and returns true.

function junk_form_validate($form, &$form_state) {
  if($form_state['values']['op'] == t('Back')) { //on the form, the button is defined with value of 'Back'
    drupal_get_messages('error');  //clears out messages thrown by built in validation
    return TRUE;
  }
  ....whatever else validation should do if they didn't press back...
}
j_ten_man’s picture

Another option is to take advantage of button specific validate and submit values for submit buttons:

function my_custom_node_form($form_state, $node) { 
  $form = array();
  // ...
  $form['cancel'] = array(
    '#type' => 'submit',
    '#value' => t('Cancel'),
    '#validate' => '', // This will cause this button to skip all validation. Put a function name here for validation with that function.
    '#submit' => 'my_custom_cancel',
  );
  return $form;
}

function my_custom_cancel($form, &$form_state) {
  $form_state['redirect'] = '';
}

This also works if you are altering the node add/edit form.

barrett’s picture

Dang! That's a lot nicer than what I had. I'll definitely have to add that trick to my repertoire. Thanks.

Apfel007’s picture

Thank you both great I will try it the second one I had nearly.... validate.. that should be the trick

mrfelton’s picture

Maybe checkout http://drupal.org/project/more_node_buttons - currently D7 only, but there is a request for a D6 version here: #784936: This looks great - any chance for a Drupal 6 backport?

--
Tom
www.systemseed.com - drupal development. drupal training. drupal support.

zhgenti’s picture

Hello guys!
Here is an example of real cancellation of required field validation. Without redirecting user to another page. You can skip validation and perform additional actions when Cancel button is clicked.
http://devengineering.com/best-practices/drupal/cancellation-required-va...

rukaya’s picture

None of the solutions here work for the /node/add/page form. I've tried adding .click functions to my cancel button to make it redirect, tried emptying the validation and submit arrays in the form, tried adding my button in an after_build function and specifying there's no validation and writing its own submit handler, I've tried adding the button into the form with javascript rather than the forms api, absolutely NOTHING works. Please if somebody thinks otherwise post and contradict me, I would love to get this working properly. In the end what I had to do was add a the cancel LINK rather than button/input into the div where my other buttons were using jquery. It is ugly and horrible and means I have to keep track of custom button text in javascript and in my custom module which is very upsetting, I'm not at all happy with it.

da_solver’s picture

The Leprechaun says this is a really easy task :)

First, you need to implement hook_form_alter() to alter the standard node form. In your hook_form_alter you need to add your custom submit handler as the the first element in the array of submit handers.

Next implement your custom submit handler.

If you look at the html source of the node form, you will notice the buttons all had a "name" attribute of "op". Therefore, you distinguish which button was clicked by inspecting the "value" attribute submitted:

function LUCKY_CHARMS_form_submit($form, &$form_state) {
    switch($form_state['values']['op']) {
        case 'Cancel' :
            drupal_set_message('Operation Cancelled');
            drupal_goto('magically/delicious');
        break;
....
    }
}

Again, the trick is to make sure you rearrange the submit handler array so that your handler is called first. In the example above, the Leprechaun redirects the user to the page who's path is mapped to "magically/delicious".

The Leprechaun says he hope this is useful.

rukaya’s picture

Hello Leprechaun! Thank you for your help. What is the array of submit handlers in the form, is it the 'buttons' array? If so then I think I did the equivalent of what you're saying in my post below, and it doesn't work :( Thank you for taking the time to try and help me though.

j_ten_man’s picture

There are two different options that you can do to avoid using jquery. If you're fine with a link (which IMO is better because it is the only easy way to get around required field validation):

/**
 * Implementation of hook_form_alter()
 */
function MODULENAME_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'NODETYPE_node_form') {
    $form['buttons']['cancel'] = array(
      '#type' => 'markup',
      '#value' => l(t('Cancel'), 'path/for/cancel'),
      '#weight' => 10,
    );
  }
}

This way will create a submit button, but it doesn't get around required field validation. There are ways to get around it (you have to remove all fields from being required - it's really ugly to say the least):

/**
 * Implementation of hook_form_alter()
 */
function MODULENAME_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'NODETYPE_node_form') {
    $form['buttons']['cancel'] = array(
      '#type' => 'submit',
      '#value' => t('Cancel'),
      '#validate' => array(''),
      '#submit' => array('my_submit_function'),
      '#weight' => 10,
    );
  }
}

function my_submit_function(&$form, &$form_state) {
  drupal_goto('path/for/cancel')
}

Both of these were tested against Drupal 6 just now and worked fine.

rukaya’s picture

I've tried the second way (because I must get around the required field validation), but it still doesn't work for me. This is my code:

function workflow_form_page_node_form_alter(&$form, &$form_state) { 
  // ... some custom stuff
  	$form['buttons']['discard'] = Array (
				'#type' => 'submit',
				'#value' => t('<  Return without saving'),
				'#weight' => 4,
				'#submit' => Array('_workflow_return_to_create_new_submit'),
				'#validate' => array(''),
	);
  // some more custom stuff 
}

function _workflow_return_to_create_new_submit($form, &$form_state) {
	// $form_state['redirect'] = '/node/add';
	drupal_goto('/node/add');
}

This makes the button appear correctly, but the validation for only TWO fields still seem to be triggered. one is the Title field which I can understand but the other is a CCK field. Is there something obviously wrong that I'm just not spotting? Thank you for your help so far.

j_ten_man’s picture

Why can't you use the link? The link will skip the required field validation always as well as any other validation. The submit button will not because of the way that drupal handles required fields - those handlers are executed before anything else - always. The solution is really ugly and I didn't put the solution to it - it would involve stepping through each field and removing the required element, and then if the person does click preview or submit then you have to go through and make sure the required fields are there in your own custom code. To say the least it's a hack and I would USE THE LINK.

rukaya’s picture

I was feeling lazy about CSSing the link so it looks like the rest of my buttons. In the end what I did was create a submit button like this:


	$form['buttons']['discard'] = Array (
		'#type' => 'submit',
		'#value' => t('<  Return to Create new without saving'),
		'#weight' => 4,
		//'#submit' => Array('_workflow_return_to_create_new_submit'),
		'#attributes' => array('class' => 'form-submit-return workflow-button-discard-create-new'),
	);

and then in a javascript file I added:

$('input.workflow-button-discard-create-new').click( function(event) {
  event.preventDefault();
  window.location = '/node/add';
});

And it works fine. Thanks for your help :)

skaught’s picture

cheers for this sample [j_ten_man]. was one of those little tricks what was making me crazy

zhgenti’s picture

Hello. Did you check the link i've posted? It's step by step tutorial there. You need to define function and assign it to form #after_build property, like this

function module_name_form_alter(&$form, &$form_state, $form_id) {
  $form['cancel_button'] = array(
    '#type' => 'submit', 
    '#value' => t('Cancel'),
    '#submit'   => array('module_name_canel_button_submit'),
  );
  $form['#after_build'][] = 'module_name_form_after_build';
}

in this function you need to iterate through all form elements and recursively unset property $element['#needs_validation']

function module_name_form_after_build($form, &$form_state) {
  unset($form['#validate']);
  if($form_state['clicked_button']['#value'] == 'Cancel') {
    _module_name_disable_validation($form);
  }
  return $form;
}

function _module_name_disable_validation(&$element) {
  unset($element['#needs_validation']);
  foreach(element_children($element) as $key) {
    _module_name_disable_validation($element[$key]);
  }
}

these actions will skip required validation and you will be able to perform your button submit handler. Until you unset '#needs_validation' property and form #validate array, your submit button handler won't be called.

then in submit handler you can do whatever you want, for example redirect to another page with drupal_goto function.

ttamniwdoog’s picture

Is it possible to remove what ever form elements that are required using jQuery.
I can hide() the elements with jQuery but if any are required, then my form fails.

Bagz’s picture

For a simple cancel button that does nothing but go back to the previous page, see the comment I added to drupal.org/node/133861

pablo.fredes’s picture

Use drupal custom module: https://www.drupal.org/project/cancel_button It works great