1

The code below is used to get the word count of a field (field_body) using ajax callback. It works great and everything functions as it should, well almost. For some reason, the click of a button is also calling the default node form submit action.

So what happens is after I update count, and suppose I don't save the content. In fact, just go to another page or refresh the page, I get something like Categories is required Tags is required Thumbnail is required....

Basically whatever I would get on form validation. It's just that the result is delayed as I am using ajax.

The problem is not with ajax, because even I comment the callback, and I click the button it tries to submit the form, when clearly it should not as executes submit callback is False.

function hook_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'article_node_form' || $form_id == 'q_and_a_node_form' ) {

    $form['get_word_count'] = array(
     '#type' => 'button',
     '#value' => t('Update Count'),
     '#weight' => 5,
     '#executes_submit_callback' => FALSE,
     '#ajax' => array(
      'callback' => 'count_words',
      ),
    );

    $form['body_words'] = array(
     '#title' => t('Words in Body'),
     '#type' => 'textfield',
     '#disabled' => TRUE,
     '#weight' => 5,
     '#prefix' => '<div id="replace_body_words">',
     '#suffix' => '</div>',
    );
   $form['field_length_type']['#prefix'] = '<div id="replace_field_length_type">';
    $form['field_length_type']['#suffix'] = '</div>'; 
  }
}

function count_words($form, $form_state) {
  $str = $form['field_body']['und'][0]['value']['#value'];
  $count = preg_match_all("/\S+/", preg_replace('/(' . chr(160) .'|&nbsp;)/', ' ', strip_tags(str_replace('><', '> <', trim($str)))), $matches);
  $form['body_words']['#value'] = $count;
  if ($count < 500) {
    $form['field_length_type']['und']['#value'] = "short";
  }
  else if ($count > 500 && $count < 800 ) {
    $form['field_length_type']['und']['#value'] = "medium";
  }
  else {
    $form['field_length_type']['und']['#value'] = "long";
  }
  return array(
    '#type' => 'ajax',
    '#commands' => array(
      ajax_command_replace("#replace_body_words", $form['body_words']),
      ajax_command_replace("#replace_field_length_type", $form['field_length_type'])
     )
   );
 }
}

Any help would be much appreciated. Any workaround?

  • 2
    Wouldn't it be easier to do this simply through JS? This way you could even show a real-time word counter. Unless you must have AJAX by design somehow or it follows up some other workflows, I think JS is by far the easiest solution. And you won't have to worry about avoiding form submittal. – Aram Boyajyan Oct 16 '13 at 19:54
  • This is a part of the snippet, there a few other things happening making JS difficult. – Pratik Bothra Oct 16 '13 at 21:26
4

When using the #type => 'button' the submit callback is never executed, it already receives a FALSE as default value.

Even if the submit callback is not executed, the validate callback is always executed (even on ajax posts). You can bypass this validation on a trigger element by using the #limit_validation_errors property.

In your case, you can set it on the body_words form element to only validate on this scope instead of the whole form.

$form['get_word_count'] = array(
    '#type' => 'button',
    '#value' => t('Update Count'),
    '#weight' => 5,
    '#limit_validation_errors' => array(
        array('body_words'),
    ),
    '#ajax' => array(
        'callback' => 'count_words',
    ),
);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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