Yii 2.0: Render a form in a Modal Popup using ajax

5 followers

Nowdays is very common webapps use this feature. With Yii2 this is very easy.

For simplicity, I'll use Yii2 basic template. You need to create a db table (I'll call Category), and generate model and CRUD with Gii. We also need a js file. So, create main.js file in web\scripts (you need to create scripts folder), and register this in \app\assets\AppAssets.php. This file will be like this:

class AppAsset extends AssetBundle
{
    public $basePath = '@webroot';
    public $baseUrl = '@web';
    public $css = [
        'css/site.css',
    ];
    public $js = [
        'scripts/main.js',
    ];
    public $depends = [
        'yii\web\YiiAsset',
        'yii\bootstrap\BootstrapAsset',
    ];
}

Now, in your views\site\index.php, put this code:

<?= Html::button(
        'create',
        ['value' => Url::to(['category/create']),
            'id' => 'modalButton'
 
        ]) ?>
 
 
    <?php
    Modal::begin([
            'id' => 'modal'
        ]);
 
    echo "<div id='modalContent'></div>";
 
    Modal::end();
    ?>

We need a button to activate the modal window. I'm using the value attribute to pass the route to the view. And starting the modal widget, and put same html tags so we can work with this.

Next, we need to chande controller\CategoryController.php to deal with ajax: (this solution came from this post)

public function actionCreate()
    {
        $model = new Category;
 
        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            $model->refresh();
            Yii::$app->response->format = 'json';
            return [
                'message' => 'Success!!!',
            ];
        }
 
        return $this->renderAjax('create', [
                'model' => $model,
            ]);
    }

And also change your views\category_form.php, so your ActiveForm call submitForm js function (solution came from the same post):

<?php $form = ActiveForm::begin([
            'id' => 'my-form-category',
            'beforeSubmit' => 'submitForm'
        ]); ?>

Last, we need the javascript code. So, put this code in web\scripts\main.js:

// listen click, open modal and .load content
$('#modalButton').click(function (){
    $('#modal').modal('show')
        .find('#modalContent')
        .load($(this).attr('value'));
});
 
// serialize form, render response and close modal
function submitForm($form) {
    $.post(
        $form.attr("action"), // serialize Yii2 form
        $form.serialize()
    )
        .done(function(result) {
            $form.parent().html(result.message);
            $('#modal').modal('hide');
        })
        .fail(function() {
            console.log("server error");
            $form.replaceWith('<button class="newType">Fail</button>').fadeOut()
        });
    return false;
}

Finish. You now have a complete form, with validation, etc. It can be in any part of your webapp.

Total 3 comments

#17800 report it
andrew1 at 2014/07/23 05:04pm
Modal

It really isn't a problem as the original submitForm function from the link above works perfectly for me. I set enableClientValidation to true in my formOptions for the \kartik\detail\DetailView I am using (I think it is true by default anyway) - no change.

Perhaps some validators don't work on the client side e.g. unique validator hence relying on the result of a submit to return errors - which aren't displayed if the modal shuts. On success I redirect. Just speculating.

Am sure the above submitForm works in some circumstances. In my circumstance the original works correctly. If it turns out to be the case that some validators don't work on client side then maybe a change - or a note added.

Cheers for the article - saved me heaps of time.

#17798 report it
thiagoc7 at 2014/07/23 08:06am
modal

You have to enable cliente side validation in ActiveForm options. Without it, the form will be submited, and js will reach .done part.

Let me know if it solves the problem, cheers!

#17792 report it
andrew1 at 2014/07/23 01:39am
Awesome but maybe a tiny error?

All works perfect except had to revert back to the done and fail functions from the original link as when validation errors occur modal closed rather than displaying validation errors. I didn't step thru but suspect entering the done function. Quite possible I mucked something up. Other than that - perfect and awesome, cheers.

Leave a comment

Please to leave your comment.

Write new article
  • Written by: thiagoc7
  • Category: How-tos
  • Yii Version: 2.0
  • Votes: +4
  • Viewed: 4,378 times
  • Created on: May 19, 2014
  • Last updated: never
  • Tags: yii2, AJAX, modal