Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Yii2: Bootstrap Modal Form Validation (Ajax) - any insight on strange behavior?

I've been working on having forms in modal windows in Yii2, and I've been having an issue where the standard Yii form ajax validation is not working when the form is inside a bootstrap modal window.

To be clear, the ajax form validation is triggered for each field when the filed looses focus. This is the standard Yii form validation, so I'm testing the form in the modal by clicking into a required field, and then clicking out of the field. This triggers the Yii ajax validation and should display a red error message under the field that states the "'field' cannot be blank."

Again, my issue is that sometimes the ajax validation works and sometimes it does not.

I managed to trap the issue to being related to where the modal code is placed on the page, but it makes no sense to me how the following would affect the ajax validation behavior of the form in the modal.

First I'll show you the code that works properly. The Yii form validation works as expected on the form in the modal window.

<?php
use yii\helpers\Html;
use yii\helpers\Url;
use yii\grid\GridView;
use yii\bootstrap\Modal;    
?>
<div class="category-index">

    <h1><?= Html::encode($this->title) ?></h1>

    <?= Html::button('Create Category', [
        'class' => 'btn btn-success btn-ajax-modal',
        'value' => Url::to('/category/create'),
        'data-target' => '#modal_category',
    ]); ?>

    <?php
    Modal::begin([
        'id' => 'modal_category',
        'header' => '<h4>Category</h4>',
    ]);
    echo '<div class="modal-content"></div>';
    Modal::end();
    ?>

    <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            ['class' => 'yii\grid\SerialColumn'],
            'id',
            'title',
            ['class' => 'yii\grid\ActionColumn'],
        ],
    ]); ?>
</div>

Things to note in the code above:

1) This is my category/index view, so it has a create button, the bootstrap modal code, and then the Yii gridview of categories.

2) The create button has the btn-ajax-modal class. This class is identified by a JS function that uses the other button attributes to display the modal widow and load the form content in the modal. The button value attribute identifies the model and form that should be loaded.

Here is the JS function that handles showing the modal and loading the form:

$('.btn-ajax-modal').click(function (){
    var elm = $(this),
        target = elm.attr('data-target'),
        ajax_body = elm.attr('value');

    $(target).modal('show')
        .find('.modal-content')
        .load(ajax_body);
});

So, all of the above code works perfectly, and my hope is that this will help others!

BUT... if I make some very simple changes to the above code, the ajax form validation no longer works, and I have no idea why.

First change:

1) Move the bootstrap modal code below the gridview code, and the ajax validation no longer works.

<div class="category-index">

    <h1><?= Html::encode($this->title) ?></h1>

    <?= Html::button('Create Category', [
        'class' => 'btn btn-success btn-ajax-modal',
        'value' => Url::to('/category/create'),
        'data-target' => '#modal_category',
    ]); ?>

    <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            ['class' => 'yii\grid\SerialColumn'],
            'id',
            'title',    
            ['class' => 'yii\grid\ActionColumn'],
        ],
    ]); ?>

    <?php //*** SEE MODAL CODE IS NOW BELOW GRIDVIEW CODE
    Modal::begin([
        'id' => 'modal_category',
        'header' => '<h4>Category</h4>',
    ]);
    echo '<div id="modalContent"></div>';
    Modal::end();
    ?>

</div>

It makes no sense to me why moving the modal code below the gridview code would break the ajax form validation. The modal still displays and loads the proper form, but the ajax form validation does not trigger when I give and remove focus to a required field.

And it gets even more bizarre ...

Second change:

2) Instead of moving the modal code below the gridview code, just delete the gridview entirely, including use yii\grid\GridView;.

<?php
use yii\helpers\Html;
use yii\helpers\Url;
use yii\bootstrap\Modal;    
?>
<div class="category-index">

    <h1><?= Html::encode($this->title) ?></h1>

    <?= Html::button('Create Category', [
        'class' => 'btn btn-success btn-ajax-modal',
        'value' => Url::to('/category/create'),
        'data-target' => '#modal_category',
    ]); ?>

    <?php
    Modal::begin([
        'id' => 'modal_category',
        'header' => '<h4>Category</h4>',
    ]);
    echo '<div class="modal-content"></div>';
    Modal::end();
    ?>

</div>

This change also causes the ajax form validation for the form in the modal to stop working.

WHAT ON EARTH? How can removing the gridview, which has absolutely nothing to do with the modal/form setup cause the ajax form validation to stop working?

I'm seeing no errors in the browser console, no errors in the Yii debug module. But for some reason, the ajax field validation is not displaying.

Sorry for such a long post, but I wanted to be as clear and specific as possible. I'm not sure if this is some strange Yii2 bug, if I'm loosing my mind, or if there is a logical explanation for this.

If anyone has any ideas, answers or suggestions, please share! And thank you for brainstorming with me!

like image 421
CICSolutions Avatar asked Apr 02 '15 03:04

CICSolutions


1 Answers

The solution to this challenge was to make sure that the form in the modal window has an id attribute. The form id is important for Yii2 ajax validation to function properly.

like image 150
CICSolutions Avatar answered Oct 23 '22 02:10

CICSolutions