MAX POWER
MAX POWER

Reputation: 5448

Yii2 - ajax validation on submit only, client validation on change

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.

Upvotes: 0

Views: 2733

Answers (1)

Muhammad Omer Aslam
Muhammad Omer Aslam

Reputation: 23738

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,
]);

Upvotes: 1

Related Questions