Tell me more ×
Drupal Answers is a question and answer site for Drupal developers and administrators. It's 100% free, no registration required.

I have several content types on a site and most of them are user-editable but not user-creatable. However, one content type, Image, allows users to upload a picture. Sometimes, however, users upload the wrong picture and they panic because they don't want that picture to be submitted to the site.

Of course they could always hit the browser's back button, but I'd like to add a Cancel button for additional assurance.

I found this thread that gives various solutions for adding cancel buttons on Drupal.org as well as this feature request for adding a cancel button to D8. However, there are several different general approaches and I don't know how to limit one to a given content type (in this case, my_image).

share|improve this question

5 Answers

up vote 2 down vote accepted

I would use the following code.

function mymodule_form_my_image_node_form_alter(&$form, &$form_state) {
  // This is a new node; the form is creating a new node.
  if (!isset($node->nid) || isset($node->is_new)) {
    $destination = 'node/add';
  }
  else {
    $destination = "node/{$node->nid}";
  }

  $form['actions']['cancel'] = array(
    '#markup' => l(t('Cancel'), $destination),
    '#weight' => 20,
  );
}  

This is the version without IF statement.

function mymodule_form_my_image_node_form_alter(&$form, &$form_state) {
  $destination = (!isset($node->nid) || isset($node->is_new)) ? 'node/add' : "node/{$node->nid}";

  $form['actions']['cancel'] = array(
    '#markup' => l(t('Cancel'), $destination),
    '#weight' => 20,
  );
}  

Notice that:

  • markup is the default form element type; there is no need to use #type = 'markup'.

  • In the node edit form, all the buttons are inside $form['actions']. The weights used from the buttons that form is using are 5 (Save), 10 (Preview), and 15 (Delete). I used 20 to show the link after those buttons, but you can change its weight to show it in a different position.

    // Add the buttons.
    $form['actions'] = array('#type' => 'actions');
    $form['actions']['submit'] = array(
      '#type' => 'submit', 
      '#access' => variable_get('node_preview_' . $node->type, DRUPAL_OPTIONAL) != DRUPAL_REQUIRED || (!form_get_errors() && isset($form_state['node_preview'])), 
      '#value' => t('Save'), 
      '#weight' => 5, 
      '#submit' => array('node_form_submit'),
    );
    $form['actions']['preview'] = array(
      '#access' => variable_get('node_preview_' . $node->type, DRUPAL_OPTIONAL) != DRUPAL_DISABLED, 
      '#type' => 'submit', 
      '#value' => t('Preview'), 
      '#weight' => 10, 
      '#submit' => array('node_form_build_preview'),
    );
    if (!empty($node->nid) && node_access('delete', $node)) {
      $form['actions']['delete'] = array(
        '#type' => 'submit', 
        '#value' => t('Delete'), 
        '#weight' => 15, 
        '#submit' => array('node_form_delete_submit'),
      );
    }
    
  • There isn't the need to use arg() to understand if the form is for editing an existing node, or for creating a new one. I checked !isset($node->nid) || isset($node->is_new) is TRUE, to verify the node is being created. Drupal seems to simply check empty($node->nid), even though node_object_prepare() uses !isset($node->nid) || isset($node->is_new).

  • If $_GET['destination'] is set, the link added with l() will point to that path.

share|improve this answer

Each node form has its own unique id. It's consisted of node type's machine name followed by _node_form. So your my_image node type's form id is my_image_node_form

Here's a mock untested function to illustrate how to implement:

function HOOK_form_alter(&$form, &$form_state, $form_id) {
  $types = array(
    'my_image',
  );

  foreach($types as $type) {
    if($type.'_node_form' == $form_id) {
      if(arg(1) == 'add') {
        // If adding node link to node/add screen
        $link = l(t('Cancel'), 'node/add');
      }
      elseif(arg(2) == 'edit') {
        // If editing node, link to node view screen
        $link = l(t('Cancel'), 'node/'.arg(1));
      }
      $form['cancel'] = array(
        '#type' => 'markup',
        '#value' => $link,
        '#weight' => 0,
      );
    }
  }
}
share|improve this answer
I added this function to my custom module, replaced HOOK with my module's name, changed my_image to the machine name of my content type, saved, and cleared the cache twice, but, although Drupal outputs no error, I also don't get a cancel button. I know you said it's untested code, but I'm unable to figure out what's wrong with this. – Patrick Kenny Jun 11 '12 at 10:43
Are you using Drupal 6 or 7? If Drupal 7 then change #value on the array to #markup – Beebee Jun 11 '12 at 12:27
I'm on D7. Thanks, that did it! – Patrick Kenny Jun 11 '12 at 12:42

You can do that using the hook form alter:

function myModule_form_alter($form_state,$form_id){
 if($form_id=='myFormId'){
  // add the cancell button to your form
 }
}

Give that a shot.

share|improve this answer
This answer is too generic; the OP is asking how to alter the edit form for a node of a specific content type. – kiamlaluno May 18 '12 at 11:27

There's a module for that!: http://drupal.org/project/nodeformsettings ... and this module is really fantastic. It's worth to check out.

share|improve this answer

All those solutions are for adding Cancel link not a button!

If you want to add the button instead of a link you should use this code for module cancel_button.module:

function cancel_button_form_alter(&$form, &$form_state, $form_id) {
    // node types for which Cancel button should be added
    $types = array(
      'biography',
      'faq',
      'draftlaw',
      'vocabulary',
      'draftlaw_page',
      'encyclopedia',
      'user', // if you want to add user's edit form too
    );

    foreach($types as $type) {
        if($type.'_node_form' == $form_id || $type.'_profile_form' == $form_id) {
            $form['actions']['cancel'] = array(
                '#type'   => 'submit',
                '#value'  => t('Cancel'),
                '#access' => TRUE,
                '#weight' => 55,
                '#submit' => array('cancel_button_form_cancel', 'node_form_submit_build_node'),
                '#limit_validation_errors' => array(),
                );
            }
        }
    }

    /**
     * cancel_button callback.
     */
    function cancel_button_form_cancel($form, &$form_state) {
        $link = '';
        $path = 'node';
        if('user_profile_form' == $form['#form_id']){
            $path = 'user';
        }
        if(arg(1) == 'add') {
            // If adding entity link to [user|node]/add screen
            $link = $path . '/add';
        }
        elseif(arg(2) == 'edit') {
            // If editing entity, link to node view screen
            $link = $path . '/' . arg(1);
        }
        $url = $_GET['destination'] ? $_GET['destination'] : $link;
        drupal_goto($url);
    }
share|improve this answer
The link was good enough for me, because I am using CSS to style my buttons anyway, and the link can be styled to look exactly the same way. – Patrick Kenny Jan 19 at 1:50
Good. My problem was the same, but with a button. So, maybe someone else likes my solution. – Peter Lozovitsky Jan 23 at 6:34

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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