1

Is it possible to enable ajax validation on form submit only, and have client / JS validation on change / blur? So for example:

  1. User inputs data and presses tab key : client validation should apply
  2. User then submits form : ajax validation should apply
  3. If validation is successful, proceed with normal form submit

Here is my ActiveForm config:

<?php $form = ActiveForm::begin([
    'id' => 'login-form',
    'enableAjaxValidation' => true,
    'enableClientValidation' => true,
    'validateOnBlur' => true,
    'validateOnChange' => true,
    'validateOnSubmit' => true,
]); ?>

Currently, when I focus out of a field, it will apply ajax validation as well - I do not want this.

13
  • what is the version of yii2 you are using? i just used the same settings and they call the ajax validation only once and onblur just calls the client validation Commented Feb 28, 2018 at 21:26
  • I am using version 2.0.13.1. I have tried this on a login form. When I enter an email address and press the tab key, I can see in the console it has performed an AJAX call. Commented Feb 28, 2018 at 22:17
  • just try updating it to the latest 2.0.14.1 with composer update and then confirm Commented Feb 28, 2018 at 22:18
  • and when you say it triggers ajax validation on blur do you mean that you see reuest inside the network tab? Commented Feb 28, 2018 at 22:20
  • Just updated to 2.0.14.1 and same thing happens. Yes, I can see the request inside the network tab. To be honest I think this is by design, because there is no way to specify whether validateOnChange and validateOnBlur will apply to ajax or client validation - it applies to both by default. Commented Feb 28, 2018 at 22:27

1 Answer 1

1

To do it the way you want it to work you need to submit the form via AJAX and it is required to attach a handler on afterValidate event. The handler will replace default form submission and is responsible for sending data to the server and displaying error messages if server validation fails. Displaying validation messages requires support on the controller side.

You can update the form name/id respectively in the script. and add the alerts in the error and incorrect server response. your form will be automatically saved via ajax call without reloading you can reset the form inside the success part.

Attach a handler to form:

$this->registerJs('$(\'#my-form\').on(\'afterValidate\', function () {
    var $yiiform = $(this);
    $.ajax({
            type: $yiiform.attr(\'method\'),
            url: $yiiform.attr(\'action\'),
            data: $yiiform.serializeArray(),
        }
    )
        .done(function(data) {
            if(data.success) {
                $yiiform.submit();
                // data is saved
            } else if (data.validation) {
                // server validation failed
                $yiiform.yiiActiveForm(\'updateMessages\', data.validation, true); // renders validation messages at appropriate places
                console.log("error on form"+data.validation);
            } else {
                console.log("incorrect server response");
                // incorrect server response
            }
        })
        .fail(function () {
            console.log("request failed");
            // request failed
        })

    return false; // prevent default form submission
})');

Just make sure you have your action coded like below

Controller action:

public function actionUpdate($id)
{
    if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {

        //call model validate to trigger validation messages
        $model->validate();

        $result = [];

        // The code below comes from ActiveForm::validate(). We do not need to validate the model
        // again, as it was already validated by save(). Just collect the messages.
        foreach ($model->getErrors() as $attribute => $errors) {
            $result[\yii\helpers\Html::getInputId($model, $attribute)] = $errors;
        }
        if (!empty($result)) {
            return $this->asJson(['validation' => $result]);
        }

        return $this->asJson(['success' => true]);

    } elseif ($model->load(Yii::$app->request->post()) && $model->save()) {
        Yii::$app->session->setFlash('success', 'Form saved successfully');
        return $this->redirect('index');
    }

    return $this->render('form', ['model' => $model]);
}

And most important just initialize your form with the option enableClientValidation as true like below.

$form = ActiveForm::begin([
    'id' => 'login-form',
    'enableClientValidation' => true,
]);
Sign up to request clarification or add additional context in comments.

1 Comment

updated the answer @GSTAR,changed a few things as we need to submit the form manually replace the event beforeSubmit with afterValidate and change the sequence of the action code to validate separately on ajax request and submit/save the model on post request once the validation passes we can submit the form via javasript .submit() in the ajax success function i just tested it and the form submits if validation passes via ajax call hope it helps you out

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.