0

I'm trying to figure out how to rebuild a form without using a button click trigger. Instead, I'm looking to rebuild whenever a blur event occurs on a textfield. All non-button form types lack the #submit value. It doesn't seem possible to trigger a form rebuild with $form_state['rebuild'] = TRUE; unless the submit callback is triggered. Demo code below.

function test_form($form, &$form_state) {
  $form['form_wrapper'] = array(
    '#prefix' => '<div id="form_wrapper">',
    '#suffix' => '</div>',
  );

  if (isset($form_state['textfield_vale'])) {
    $textfield_vale = $form_state['textfield_vale'];
  }
  else {
    $textfield_vale = 'not set';
  }

  //will not trigger page rebuild
  $form['form_wrapper']['test_textfield'] = array(
    '#type' => 'textfield',
    '#value' => 'Value = '.$textfield_vale,
    '#ajax' => array(
      'callback' => 'test_result',
      'wrapper' => 'form_wrapper',
      'event' => 'blur',
     ),
  );

  //will trigger page rebuild, changing the textfield value
  $form['form_wrapper']['trigger_rebuild'] = array(
    '#type' => 'submit',
    '#value' => 'I don\'t want to press it',
    '#submit' => array('submit_rebuild'), //has #submit value unique to buttons
    '#ajax' => array(
      'callback' => 'test_result_with_button',
      'wrapper' => 'form_wrapper',
    ),
  );

  return $form;
}

function test_result($form, &$form_state) { //unable to set $form_state['rebuild'] = TRUE
  $form_state['textfield_vale'] = 'textfield trigger'; //TRUE;
  $form_state['rebuild'] = TRUE;
  return $form['form_wrapper'];
}

function submit_rebuild($form, &$form_state) {
  $form_state['textfield_vale'] = 'button trigger'; //TRUE;
  $form_state['rebuild'] = TRUE;
}

function test_result_with_button($form, $form_state) {
  return $form['form_wrapper'];
}

Is there a way to trigger a form rebuild without clicking a button (perhaps with an ajax command)? Alternatively, how can I change my code to allow an ajax callback to change $form_state values?

9
  • If not a button what else should trigger the rebuild? Onchange?
    – leymannx
    Commented Jul 29, 2019 at 17:27
  • Preferably a blur event, but onchange would work as well.
    – Ghoti
    Commented Jul 29, 2019 at 17:42
  • How is that blur being triggered?
    – leymannx
    Commented Jul 29, 2019 at 18:01
  • 1
    Have you tried drupal.stackexchange.com/a/126952/15055?
    – leymannx
    Commented Jul 29, 2019 at 18:05
  • 1
    I think this GET thing only comes from the question's code and isn't actually necessary for the autosubmit to work. But I'm unsure about that.
    – leymannx
    Commented Jul 29, 2019 at 18:38

2 Answers 2

0

I've always handled changing form values in the form build or form_alter function itself. I can't remember where I saw to do this, but I've never been able to alter the form in the ajax callback itself.

Have your form trigger an ajax callback. This should return the form or piece of the form in question, like your test_result_with_button() function.

When an ajax callback is triggered, the build method and alters are run again. Add logic in your build / form_alter to make updates to the form or form_state based on whichever action was triggered. Information about how the rebuild was triggered will be available in $form_state['triggering_element'].

1
  • I haven't been able to update the form after AJAX callback. I can change variable values but the form elements will not change unless $form_state['rebuild'] is called. I think I might be able to get what I want with careful javascript. And to clarify, I'm trying to change the attributes of elements (disable some buttons, change the text of a textfield). Replacing them with AJAX will cause problems.
    – Ghoti
    Commented Jul 29, 2019 at 22:03
0

I've found that jQuery can be used to click a Drupal submit button (source). I can use an event listener to trigger a submit event by interacting with a specific button that can be hidden anywhere on the form. Below is my solution based off of my original demo code.

<?php

function test_form($form, &$form_state) {
  drupal_add_js('
(function ($) {
  Drupal.behaviors.test_form = {
    attach: function() {
      $("#test_textfield").blur(function() {
        $("#trigger_rebuild").mousedown();
      });
    }
  }
}(jQuery))', 'inline');

  $form['form_wrapper'] = array(
    '#prefix' => '<div id="form_wrapper">',
    '#suffix' => '</div>',
  );

  if (isset($form_state['textfield_vale'])) {
    $textfield_vale = $form_state['textfield_vale'];
  }
  else {
    $textfield_vale = 'not set';
  }

  //will not trigger page rebuild
  $form['form_wrapper']['test_textfield'] = array(
    '#type' => 'textfield',
    '#value' => 'Value = '.$textfield_vale,
    '#id' => 'test_textfield',
  );

  //will trigger page rebuild, changing the textfield value
  $form['form_wrapper']['trigger_rebuild'] = array(
    '#type' => 'submit',
    '#value' => 'I don\'t want to press it',
    '#id' => 'trigger_rebuild',
    '#submit' => array('submit_rebuild'), //has #submit value unique to buttons
    '#ajax' => array(
      'callback' => 'test_result_with_button',
      'wrapper' => 'form_wrapper',
    ),
  );

  return $form;
}

function submit_rebuild($form, &$form_state) {
  $form_state['textfield_vale'] = 'button trigger'; //TRUE;
  $form_state['rebuild'] = TRUE;
}

function test_result_with_button($form, $form_state) {
  return $form['form_wrapper'];
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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