0

I have a form, which is made up of a listbox and a textarea, the listbox holds a number of items that related to records in the database. The user can select an item from the listbox and select the retrieve button (which is of type submit) the record selected is retrieved from the database and the textfield on the form is updated to show one of the fields from the database record (e.g. answer). The form looks like this:

enter image description here

The first time a record is selected from the listbox and the retrieve button is selected - the form functions as expected e.g. the callback function is run, the section of the form is updated (rather than the whole form updating) and the textarea is updated to show the database entry.

On the second run, however, when a record is selected from the listbox and the retrieve button is pushed - rather than the textarea updating to show the selected record... the form looks like it completely refreshes and reloads rather than calling the callback function as it does in the first run.

On the third attempt the form works correctly again - but, that's no doubt because the form looks like it reloads on the second go - rather than the callback function running.

The form's buildForm function is as follows:

    public function buildForm(array $form, FormStateInterface $form_state)
{
    // TODO: Implement buildForm() method.

    $this->app_instance_id=\Drupal::request()->query->get('api');

    $form=array();

    $this->set_listbox_options();

    $form['page']=array(

        "#prefix"=>"<div class='row'><div class='col-md-12'>",
        "#suffix"=>"</div></div>",
    );

    $form['page']['fieldset_1']=array(
        "#prefix"=>"<div id='wrapper_tab1_q1' class='row'><div class='col-md-12'>",
        "#suffix"=>"</div></div>",
    );
    $form['page']['fieldset_1']['row1']=array(
        "#prefix"=>"<div class='row'><div class='col-md-12'>",
        "#suffix"=>"</div></div>",
    );
    $form['page']['fieldset_1']['row2']=array(
        "#prefix"=>"<div class='row'><div class='col-md-12'>",
        "#suffix"=>"</div></div>",
    );
    $form['page']['fieldset_1']['row3']=array(
        "#prefix"=>"<div class='row'>",
        "#suffix"=>"</div>",
    );
    // ----------- ---------------------
    $form['page']['fieldset_1']['row3']['column1']=array(
        "#prefix"=>"<div class='".$this->col1_width."'>",
        "#suffix"=>"</div>",
    );
    // ---------- ----------------------
    $form['page']['fieldset_1']['row3']['column1']['the_answer']=array(
        "#type"=>"textarea",
        '#attributes' => array(
            'rows'=>'9',
        ),
        "#prefix"=>"<div class='row'><div class='col-md-12'>",
        "#suffix"=>"</div></div>",
    );
    // ---------- ----------------------
    $form['page']['fieldset_1']['row3']['column2']=array(
        "#prefix"=>"<div class='".$this->col2_width."'>",
        "#suffix"=>"</div>",
    );
    $form['page']['fieldset_1']['row3']['column2']['record_select_list']=array(
        "#type"=>"select",
        "#options"=>$this->listbox_options,
        '#attributes' => array(
            'width'=>'10',
            'size'=>'8',
            'multiple'=>'multiple',
        ),
        "#prefix"=>"<div class='row'><div class='col-md-12'>",
        "#suffix"=>"</div></div>",
    );
    $form['page']['fieldset_1']['row3']['column2']['submit_list_selection']=array(
        "#type"=>"submit",
        "#value"=>"Retrieve",
        "#ajax"=>array(
            "callback"=>"::run_callback_code",
            "wrapper"=>"wrapper_tab1_q1",
        ),
        "#prefix"=>"<div class='row'><div class='col-md-12'>",
        "#suffix"=>"</div></div>",

    );
    // ----------- ---------------------
    $form['page']['fieldset_1']['row4']=array(
        "#prefix"=>"<div class='row'><div class='col-md-12'>",
        "#suffix"=>"</div></div>",
    );

    return $form;
}

The callback function "run_callback_code" is as follows:

    public function run_callback_code (array &$form, FormStateInterface $form_state)
{


    // ---------------------------------------------

    $listbox_selection=$form_state->getValue("record_select_list");


    $answer_db_object=new db_select();
    $answer_db_object->set_setTable("tbl_frm1_tab1_q1_ans");


    $qry_fields=[
        'frm1_tab1_q1_ans_id',
        'data_request_app_instance_id',
        'user_id',
        'answer',
    ];

    $answer_db_object->set_fieldArray($qry_fields);

    $qry_fieldValues[0]['field']="frm1_tab1_q1_ans_id";
    $qry_fieldValues[0]['condition']="";
    $qry_fieldValues[0]['type']="";
    $qry_fieldValues[0]['value']=$listbox_selection;

    $answer_db_object->set_condition($qry_fieldValues);

    $results=$answer_db_object->select_qry();

    $form['page']['fieldset_1']=array(
        "#prefix"=>"<div id='wrapper_tab1_q1' class='row'><div class='col-md-12'>",
        "#suffix"=>"</div></div>",
    );
    $form['page']['fieldset_1']['row1']=array(
        "#prefix"=>"<div class='row'><div class='col-md-12'>",
        "#suffix"=>"</div></div>",
    );
    $form['page']['fieldset_1']['row2']=array(
        "#prefix"=>"<div class='row'><div class='col-md-12'>",
        "#suffix"=>"</div></div>",
    );
    $form['page']['fieldset_1']['row3']=array(
        "#prefix"=>"<div class='row'>",
        "#suffix"=>"</div>",
    );
    // ----------- ---------------------
    $form['page']['fieldset_1']['row3']['column1']=array(
        "#prefix"=>"<div class='".$this->col1_width."'>",
        "#suffix"=>"</div>",
    );
    // ---------- ----------------------
    $form['page']['fieldset_1']['row3']['column1']['the_answer']=array(
        "#type"=>"textarea",
        '#attributes' => array(
            'rows'=>'9',
        ),
        "#prefix"=>"<div class='row'><div class='col-md-12'>",
        "#suffix"=>"</div></div>",
    );

    if (is_array($results)){
        if (sizeof($results)>0){
            $form['page']['fieldset_1']['row3']['column1']['the_answer']['#value']=$results[0]->answer;
        }
    }
    // ---------- ----------------------
    $form['page']['fieldset_1']['row3']['column2']=array(
        "#prefix"=>"<div class='".$this->col2_width."'>",
        "#suffix"=>"</div>",
    );
    $form['page']['fieldset_1']['row3']['column2']['record_select_list']=array(
        "#type"=>"select",
        "#options"=>$this->listbox_options,
        '#attributes' => array(
            'width'=>'10',
            'size'=>'8',
            'multiple'=>'multiple',
        ),
        "#prefix"=>"<div class='row'><div class='col-md-12'>",
        "#suffix"=>"</div></div>",
    );
    $form['page']['fieldset_1']['row3']['column2']['submit_list_selection']=array(
        "#type"=>"submit",
        "#value"=>"Retreive",
        //"#submit"=>array("::run_submit_code"),
        "#ajax"=>array(
            "callback"=>"::run_callback_code",
            "wrapper"=>"wrapper_tab1_q1",
        ),
        "#prefix"=>"<div class='row'><div class='col-md-12'>",
        "#suffix"=>"</div></div>",

    );
    // ----------- ---------------------
    $form['page']['fieldset_1']['row4']=array(
        "#prefix"=>"<div class='row'><div class='col-md-12'>",
        "#suffix"=>"</div></div>",
    );

    $form_state->setRebuild();
    return $form['page']['fieldset_1'];
}

I have not added any code to the validation and submit functions as yet, because I haven't been able to get the form to function as required and so have not included them here.

Does anyone know, why the form appears to reload on the second/forth/sixth attempt rather than continuing to call the callback function? (Even if I remove the $form_state->setRebuild () line of code the form continues to refresh itself on the second/forth/sixth etc goes). The reason I am using a callback e.g. ajax is so that only part of the form is updated at run-time rather than the whole form.

Side Note: The is bespoke code written related to running the select query, which is used in the callback function, but that shouldn't impact the form as it's purely just dealing with retrieving data from the database using the standard Database API.

  • I found some information, which I think might shed some light on what is happening e.g. link as the information on the page hightlights, for any button there will back a callback and a defaulting to the submit function if no bespoke function is defined... This being said, even if I define a bespoke function e.g. "#submit"=>array ("::run_submit_code") this doesn't seem to resolve the fact that the form continues to reload rather than calling the callback function on the 2nd/4th/6th etc attempt – Mo-ster Mar 27 '17 at 3:48
  • Also, I have tried '#limit_validation_errors' => array() as suggested (e.g. even though the question looks like it's talking about Drupal 7 link ) in a couple of posts, but I'm finding it doesn't resolve the issue in my case – Mo-ster Mar 27 '17 at 4:47
0

Extrapolating from the link Mo-ster shared, add this to your form element:

'#attributes' => array('onclick' => 'return (false);')

The API says that buttons trigger a validate and rebuild, but not a submit: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Render%21Element%21Button.php/class/Button/8.2.x

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.