Search code examples
drupal-7drupal-formsdrupal-fapidrupal-ajax

How to create an image button that behaves like a button in drupal 7?


How I want it to work:

I have list of buttons(type button) that trigger an Ajax call that add the that item to a list. This works as exactly as I want it except for the button looks ugly .

The problem:

When I try to replace the "button" with an "image button" the form is submitted, which is not what I want. Is there a way to add an image to a button that do not trigger a submit? Can I disable the submit for "image button"? Or shall I add the image using css on the button?

What is the difference between "button", "image button" and "submit"?


Solution

  • To make the type image_button act like an button is looked in system.module and found "'#executes_submit_callback' => TRUE", so change this to false will prevent submit function to be called on your image_button.

    Code from system.module:

    $types['button'] = array(
        '#input' => TRUE,
        '#name' => 'op',
        '#button_type' => 'submit',
        '#executes_submit_callback' => FALSE,
        '#limit_validation_errors' => FALSE,
        '#process' => array('ajax_process_form'),
        '#theme_wrappers' => array('button'),
    );
    $types['image_button'] = array(
        '#input' => TRUE,
        '#button_type' => 'submit',
        '#executes_submit_callback' => TRUE,   // <--- This is why submit is triggered
        '#limit_validation_errors' => FALSE,
        '#process' => array('ajax_process_form'),
        '#return_value' => TRUE,
        '#has_garbage_value' => TRUE,
        '#src' => NULL,
        '#theme_wrappers' => array('image_button'),
    );
    

    Another thing that you might encounter is the validation error, to remove it just add the "'#validate' => array()" or if you want to run validation but ignore errors use "#limit_validation_errors' => array()". This also apply for button.

    Here is an example where you can experiment the above things and see when the validation and submit callback is triggered. Also a checkbox is included to show when validation errors occurs.

    function button_menu()
    {
        $items = array();
    
        $items['button'] = array(
            'title'           => 'Button',
            'page callback'   => 'drupal_get_form',
            'page arguments'  => array('button_form'),
            'access callback' => array(TRUE),
            'type'            => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    function button_form($form, &$form_state)
    {
        // Add to prove the point of how validation is working
        $form['checkbox'] = array(
            '#type'          => 'checkbox',
            '#title'         => t('checkbox'),
            '#default_value' => FALSE,
        );
    
        $form['button'] = array(
            '#id'       => 'button_1',
            '#type'     => 'button',
            '#name'     => 'test1',
            '#value'    => 'test1',
            //'#validate' => array(),  // This line will remove validation completely
            '#limit_validation_errors'  => array(), // This line will run validation but ignore any errors
            '#ajax'     => array(
                'callback' => 'button_test_callback',
                'wrapper'  => 'wrapper',
                'method'   => 'replace',
                'effect'   => 'fade',
            ),
        );
    
        $form['image_button'] = array(
            '#id'                       => 'image_button_1',
            '#type'                     => 'image_button',
            '#src'                      => '/themes/bartik/logo.png', // hope you still have bartik theme
            '#executes_submit_callback' => FALSE,   // This line removes the submit callback
            //'#validate' => array(),               // This line will remove validation completely
            '#limit_validation_errors'  => array(), // This line will run validation but ignore any errors
            '#ajax'                     => array(
                'callback' => 'button_test_callback',
                'wrapper'  => 'wrapper',
                'method'   => 'replace',
                'effect'   => 'fade',
            ),
        );
    
        // Just some code to show what button was pressed
        if (array_key_exists('triggering_element', $form_state) &&
            ($form_state['triggering_element']['#id'] == 'button_1' || $form_state['triggering_element']['#id'] == 'image_button_1'))
        {
            $form['markup'] = array(
                '#type' => 'markup',
                '#markup' => '<div id="wrapper"><p>'. $form_state['triggering_element']['#id'] .'</p></div>',
            );
        }
        else {
            $form['markup'] = array(
                '#type' => 'markup',
                '#markup' => '<div id="wrapper"><p>nothing</p></div>',
            );
        }
    
        $form['submit'] = array(
            '#type'  => 'submit',
            '#value' => 'Submit',
        );
    
        return $form;
    }
    
    function button_test_callback($form, $form_state)
    {
        return $form['markup'];
    }
    
    function button_form_validate($form, &$form_state)
    {
        // To display when validation is triggered
        drupal_set_message('button_form_validate');
    
        // Only when submit button is pressed we care about this error.
        if ( $form_state['values']['checkbox'] == 0) {
            form_set_error('checkbox', 'checkbox not checked');
        }
    
    }
    
    function button_form_submit($form, &$form_state)
    {
        // To display when submit is triggered
        drupal_set_message('button_form_submit');
    }