How to return invalid password error message via Ajax and display error message above form without page refresh

When a user enters an incorrect username/password combination and clicks Submit button, I want to return an error message and display it to the user above the form without a page refresh.

I’m assuming this is the function that handles the generation of the error message, but I don’t know how to return it to be used in the UI.

common\models\LoginForm.php:




 public function validatePassword($attribute, $params)

    {

        if (!$this->hasErrors()) {

            $user = $this->getUser();

            if (!$user || !$user->validatePassword($this->password)) {

                $this->addError($attribute, 'Incorrect username or password.');

            }

        }

    }



The following code works to authenticate the user just fine and as you can see I’ve disable the goHome() function in order to authenticate without page refresh…

backend\controllers\SiteController.php:




public function actionLogin()

    {

        if (!\Yii::$app->user->isGuest) {

            //return $this->goHome();

        }


        $model = new LoginForm();

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

            //return $this->goBack();

        } else {

            return $this->render('login', [

                'model' => $model,

            ]);

        }

    }



you can enable the ajax validation in your form, here is good place to start

http://www.yiiframework.com/doc-2.0/guide-input-validation.html#ajax-validation

Thanks – so I’ve modified my actionLogin which returns the errors that I want in JSON format but I don’t know how to make the $errors variable available to be used by JQuery – do you know how I can transfer this variable to Javascript so I can add to UI?

Here is my action code in case anyone else is wondering how to do this –

backend\controllers\SiteController.php:




public function actionLogin()

    {

        if (!\Yii::$app->user->isGuest) {

            //return $this->goHome();

        }


        $model = new LoginForm();


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

            //return $this->goBack();

            //echo 1;




        } else {

// populate model attributes with user inputs

            $model->attributes = \Yii::$app->request->post('LoginForm');

            Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

            if ($model->validate()) {

                // all inputs are valid

            } else {

                // validation failed: $errors is an array containing error messages

                $errors = $model->errors;

                //return $errors;

                echo $errors;


            }





            //return $this->render('login', [

            //  'model' => $model,

            //]);

        }

    }



Thanks

OK I figured it out, here is what I did in case anyone is interested –

The idea is to use Javascript to disable the default behavoir of the form and to use JQuery to send a post request using your form action (site/login) and make sure to set the Response to JSON and return it.

Then you can access the returned JSON object like "result.property"…

backend\controllers\SiteController.php:




public function actionLogin()

    {

        if (!\Yii::$app->user->isGuest) {

            //return $this->goHome();

        }


        $model = new LoginForm();


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

            //return $this->goBack();

            //echo 1;

            // populate model attributes with user inputs

            

            if ($model->validate() && $model->login()) {

                // all inputs are valid

                // echo successful;

            } else {

                $model->attributes = \Yii::$app->request->post('LoginForm');

                \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

                // validation failed: $errors is an array containing error messages

                $errors = $model->errors;

                //return $errors;

                return $errors;

                }

            } else {

            

            return $this->render('login', [

              'model' => $model,

            ]);

        }

    }



backend\views\site\login.php:




<?php 


$script = <<< JS


$('form#login-form').on('beforeSubmit', function(e)

{

    var \$form = $(this);

    $.post(


        \$form.attr("action"), //serialize yii2 form

        \$form.serialize()

    )

        .done(function(result) {

            if(result.password == null) {

            alert('null, success!');

        }else{

            $('#status-bar').empty();

            $('#status-bar').append('<div class="alert alert-success alert-dismissible"><button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">x</span></button>' + result.password + '</div>').hide().slideDown();

            //$.pjax.reload({container:'#login-form'});

            //$(\$form).trigger("reset");

            alert('fail');

        }

            });

        return false;

});




JS;

$this->registerJs($script);

?>



Hope this helps!! Cheers