Render a form in a Modal Popup using ajax [Fixed]

First of all, sorry by my english.

I saw this (www.yiiframework.com/wiki/690/render-a-form-in-a-modal-popup-using-ajax) article, but it’s with some bugs.

I needed this function in my app, so I got this thing working, now I’m here to show how I did it.

Just for knowing, the article teach about puting a button that calls a modal in your site. I’m going to do a button that calls a modal in your form, getting back the Id to you proced in your form.

Folowing the article, you must create a Js file and add the file on your assets file:


class AppAsset extends AssetBundle

{

    public $basePath = '@webroot';

    public $baseUrl = '@web';

    public $css = [

        'css/site.css',

    ];

    public $js = [

        'scripts/myScript.js',

    ];

    public $depends = [

        'yii\web\YiiAsset',

        'yii\bootstrap\BootstrapAsset',

    ];

}

Now, in your views\myFirst\_form.php, put this code(here we have some changes):





    <?= Html::activeHiddenInput($model, 'myAttribute') ?>


    <?= Html::button(

        'myAttribute...', 

        ['value' => $model->isNewRecord 

                    ?Url::to(['mySecond/create'])  //Put here the url to the Create page

                    :Url::to(['mySecond/update','id'=>$model->myAttribute]), //and here to the update Page with the id attribute

            'id'=>'changeMyAttribute',

            'for'=>'#myModel1-myAttribute' //Put here the id of the field you want to update 

        ]) 

    ?>


    .... 


 

    <?php

    Modal::begin(['id' => 'myModal']);

 

    echo "<div id='myModalContent'></div>";

 

    Modal::end();

    ?>



This will put the button and the base for our modal. In the button I’m using the value to pass the Url and the for to indicate wich field update. You can change it, but you must change in other places too.

Going on, we need to change the Create and the Update actions of our Controller.

Open controller\MySecondController.php and do the changes needed.




    public function actionCreate()

    {

        $model = new address();


        if ($model->load(Yii::$app->request->post()) && $model->save()) {

            $model->refresh();

            Yii::$app->response->format = 'json';

            return ['message' => Yii::t('app','Success Create!'), 'id'=>$model->id];

        }

        return $this->renderAjax('create',['model'=>$model]);

    }





    ....





    public function actionUpdate($id)

    {

        $model = $this->findModel($id);


        if ($model->load(Yii::$app->request->post()) && $model->save()) {

            $model->refresh();

            Yii::$app->response->format = 'json';

            return ['message' => Yii::t('app','Success Update!'), 'id'=>$model->id];

        }

        return $this->renderAjax('update',['model'=>$model]);

    }




Now we are going to change our second view to accept the BeforeSubmit.

On views\myDecond\_form.php, change the ActiveForm declararion:




    <?php $form = ActiveForm::begin([

        'id' => $model->formName()

    ]); ?>

    

    

    <?php

    //beforeSubmit

    $js = "

        $('form#".$model->formName()."').on('beforeSubmit', function(e){

            var \$form = $(this);

            submitMySecondForm(\$form);

        }).on('submit', function(e){

            e.preventDefault();

        });";

    $this->registerJs($js);

    ?>




This solution I got from: www.ramirezcobos.com/2014/09/12/how-to-implement-form-events-on-yii2/

Finally, we need to create our script.(Yeah, we could put with registerJs, but I don’t like it…)


$("#changeMyAttribute").click(function(){

    $("#myModal").modal('show')

            .find("#myModalContent")

            .load($(this).attr('value'));

});


function submitMySecondForm($form){

    $.post(

        $form.attr("action"),

        $form.serialize()

    )

        .done(function(result){

            $form.parent().html(result.message);

            $($("#changeMyAttribute").attr('for')).attr('value', result.id); //actualize the ID on the input hidden

            $("#changeMyAttribute").attr('value','/index.php?r=mySecond%2Fupdate&id='+result.id); //change here to the url of update view.

            $('#myModal').modal('hide');

        })

        .fail(function(){

            console.log("server error");

            $form.replaceWith('<button>Fail</button>').fadeOut()

        });

    return false;

}



and it’s done.

If anyone has some help to improve this, feel free to coment. I think that isn’t the best way to do this, but it’s working well, and isn’t hard to do.

Thanks Francisco

I wrote a wiki about this… You should look at the js portion and comments. You should switch some of your js functions to use on instead of click bs you will loose the Dom elements when it loads initially and will not let the popup render again without refresh.

http://www.yiiframework.com/wiki/806/render-form-in-popup-via-ajax-create-and-update-with-ajax-validation-also-load-any-page-via-ajax-yii-2-0-2-3/