Yii2: Tips & Tricks

Thanks Orey, that worked perfectly once I updated the correct file. I think with the advanced template, you have to do it for both frontend and backend in config/main.php.

Just my opinion, but I find your tips very useful and insightful. Often we can find out how something is done in docs, but not always why it is done or how cool or useful it really is. This is invaluable for someone who wants to learn and grow and this forum is the perfect place for that, so thanks again.

You are doing a great job mate. Keep it up.

BTW … not that it matters, your english is greater/better than many.

Ok, now it’s time to submit some forms.

First of all, we configure our ActiveForm slightly, to set our onsubmit listener.

Best way (the only way?..) to do it is beforeSubmit, it fires after client validation, but before actual submit.

Handler function takes one argument: "jqueryfied" form.


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

    'id' => 'my-form-id', // Optional. I just like to keep things under control

    'validateOnType' => true, // Optional, but it helps to get rid of extra click

    'beforeSubmit' => new \yii\web\JsExpression('function($form) {

        $.post(

            $form.attr("action"),

            $form.serialize()

        )

        .done(function(result) {

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

        })

        .fail(function() {

            console.log("server error");

        });

        return false;

    }'),

]); ?>

As you can see, I’ve set beforeSubmit callback that calls well-known jquery’s ajax post().

I can take submit url from default form’s action using $form.attr(“action”).

In case of successful ajax call, I can take the result and do whatever I want. Here I’m just replacing form’s parent element.

If you hate writing JS inside PHP (as I do), you can just pass the name of the handler function:


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

    'beforeSubmit' => 'postForm',

]); ?>



and then write actual processing code somewhere else:


<script>

function postForm($form) {

    $.post(

        $form.attr("action"),

        $form.serialize()

    )

    .done(function(result) {

        if (typeof(result) === "string") {

            // form is invalid, html returned

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

        } else {

            // form is valid and saved, json returned

            if (result.redirect) {

                window.location = result.redirect; // ok, that's weird, but who cares?..

            };

        }

    })

    .fail(function() {

        console.log("server error");

    });

    return false;

}

</script>

In this example I have extra check for typeof(result), so that I can return HTML or JSON from controller’s action.

Now the controller part.

Here’s simple action that renders the ‘_create’ partial view (that is, our form) in case of server validation failure,

or ‘_success’ partial view in case of saving.


public function actionCreate()

{

    $view = '_create';

    $record = new MyModel;


    if ($record->load($_POST) && $record->save()) {

        $record->refresh(); // just in case of some DB logic

        $view = '_success';

    }


    return $this->renderAjax($view, [

        'record' => $record,

    ]);

}

Or you can return HTML in case of error and JSON in case of success. Or something else. It’s up to you.


public function actionCreate()

{

    $record = new MyModel;


    if ($record->load($_POST) && $record->save()) {

        $record->refresh(); // just in case of some DB logic

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

        return [

            'record' => $record->toArray(),

            'redirect' => Url::toRoute(['site/somewhere', 'from' => 'created']),

        ];

    }


    return $this->renderAjax('edit', [

        'record' => $record,

    ]);

}



As you have noticed, renderAjax() is used to render the partials.

It’s a special function that not only renders the view, but also adds JS and CSS files registered from the view.

Check this and this for details.

[b]BTW I would be happy if someone will review my code and tell me if I’m wrong, or there’s a better way.

Srsly guys.[/b]

And here’s how we can hack ActiveForm’s JS a litte bit.

As you probably know[color="#FF0000"]*[/color], you can use data-confirm attribute to prevent user from accidental mouse clicking:


<button type="submit" data-confirm="Are you sure?">delete this</button>

But who wants alerts? Alerts are crap.

Here’s what we do:


<script>

yii.allowAction = function ($e) {

    var message = $e.data('confirm');

    if (message === undefined) {

        return true; // not protected

    } else if ($e.data('_confirm')) {

        $e.html("Removing...");

        return true; // protected and confirmed

    } else {

        $e.html(message); // asking for confirmation RIGHT ON THE BUTTON

        $e.data('_confirm', true); // setting a flag

    }

    return false;

}<script>

In this case first click on the button changes it’s text to confirmation message, and only second passes.

I’m pretty sure you can create your own cool confirmation system this way.

[color="#FF0000"]*[/color] Actually, I found this by chance while creating my own implementation. So I just added data-confirm (without any js yet), clicked a button for some reason and OOPS WHAT WAS THAT? :blink:

ORey, currently it is hard to review code since you dont group it ) How about also to post this tips and tricks to coderwall ? That would be useful )

Hmm, never heard of that before.

You mean https://coderwall.com ?

Ok, I’ll take a look, thx.

yes, this one. It would be handy since it has favorites, tags and other things.

Very, very good initiative!

Congratulations.

I’m hoping that a repository of tips and complete and comprehensive code is created.

I’m planning to collect these and write a cookbook similar to the one for 1.1. This time it will be opensourced.

Nice job Orey and thanks for sharing this!

Maybe the Yii-team can create a git repository (yii2-cookbook) where people can submit PR´s with small recipes/examples like Orey have done here. The repository could compose primarily of files with markdown syntax (*.md). And then on each commit, the cook book is generated and published to the website (just as the documentation).

What do you think?

Done: https://github.com/samdark/yii2-cookbook

I’ll be your editor :)

Nice start.

Cool.

Probably I should learn git eventually, cause all the good stuff happens on github :)

Svn is totally outdated :(

Yeah. github is opensource everything ;)

You are fast as always Samdark ;)

Just found this: Gitbook.

Maybe it can be used to generate the book itself? Or would it be to much/complicated to start with?

exciting news for creating the yii2 cookbook . we need this :lol:

Interesting this, huh!

It’s starting to take a shape: https://github.com/samdark/yii2-cookbook/blob/master/book/index.md Come on, let’s do it!

Love the cookbook, these are very useful tips. I hope more people contribute…