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

15 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 11 comments

#18495 report it
robsch at 2014/11/06 09:30am
Setting unknown property: yii\widgets\ActiveForm::beforeSubmit

@EndErr: I had also some troubles with this but now it's working. I didn't add the parameter beforeSubmit to the ActiveForm. I have just added an normal event handler for beforeSubmit with jQuery.

But what also makes me wonder is what would happen if client validation is okay but on the server save returns false. What should happen then? In this case the form would be returned, instead of json data. I'm not sure how to deal with this...

#18474 report it
EndErr at 2014/11/04 07:39am
Setting unknown property: yii\widgets\ActiveForm::beforeSubmit

Could anyone explain how to make it work? If I do like andrew1 suggested (using a standard ActiveForm) but I get a error:

Setting unknown property: yii\widgets\ActiveForm::beforeSubmit
#18379 report it
sifa786 at 2014/10/22 10:29am
All working

@andrew1 - Thanks so much - you are a star! I got it all working now .... @thiagoc7 - I of course understand, thanks for taking the time to respond anyway!

#18368 report it
andrew1 at 2014/10/21 07:29pm
Updated submitform

@sifa786

currently in my web/main/main.js I have

function submitform(id) {
    // get the form id and set the event handler
    $('form#' + id).on('beforeSubmit', function(e) {
        var form = $(this);
        $.post(
            form.attr("action"),
            form.serialize()
        )
        .done(function(result) {
            form.parent().html(result);
        })
        .fail(function() {
            console.log("server error");
        });
        return false;
    }).on('submit', function(e){
        e.preventDefault();
    });
}

and I register this in my form view widget with (actually using Kragee detail view widget so this is in my overriding run method)

$this->getView()->registerJs(";submitform('{$this->formOptions['id']}');");

Naturally you need to alter the form id variable to suit.

#18367 report it
thiagoc7 at 2014/10/21 07:15pm
I can't help now

I'm no longer developing this project with Yii2, will came back next year... Sorry, but I can't help.

#18366 report it
sifa786 at 2014/10/21 07:04pm
please update code as per latest release?

beforeSubmit is no longer available on ActiveForm - http://www.ramirezcobos.com/2014/09/12/how-to-implement-form-events-on-yii2/ is supposed to fix this, but I am unable to get it to work ... i need a complete example, pls?

#18174 report it
andrew1 at 2014/09/20 10:53pm
beforeSubmit gone from ActiveForm in latest version

@thiagoc7 beforeSubmit is gone now from ActiveForm - http://www.ramirezcobos.com/2014/09/12/how-to-implement-form-events-on-yii2/ seems to fix it.

#17977 report it
mrdantez at 2014/08/20 08:36am
Error 500

Hi, I used the instructions following the wiki, when I submit the form, it returns an Error 500, Internal Server Error. Thank you.

#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: +6
  • Viewed: 18,613 times
  • Created on: May 19, 2014
  • Last updated: never
  • Tags: yii2, AJAX, modal