user3033990 user3033990 - 5 months ago 206
Ajax Question

Yii2: ajax form validation on an ajax submitted form

I'm wondering if any Yii2 experts can help me understand how best to work with ajax forms combined with Yii ajax validation. I think I can explain the issue without taking you through all of my code.

I am working on a Promo Code entry form where the user enters their promo code into the form, the form is submit via ajax. We then perform a database lookup for the promo code details, validate the code and if the code validates, we want to display the registration form that is hidden on the page.

I have a custom validation function for the form field "code", which is the active field in a model scenario named "register".

class UserCode extends ActiveRecord
{
...

public function scenarios()
{
return [
'register' => ['code'],
];
}

public function rules()
{
return [
[['code'], 'required'],
[['code'], 'validateUserCode', 'on' => ['register']],
];
}

public function validateUserCode($attribute, $params)
{
// perform all my custom logic to determine if the code is valid

if ($code_invalid) {
$this->addError($attribute, 'Sorry, this code is invalid.');
}
}

...
}


Then in the controller, as the Yii2 Guide suggests, I trap this ajax validation with the following code:

public function actionValidate() {

$model = new UserCode(['scenario' => 'register']);

if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}

// no logic can be run after the above code b/c the form is submit with ajax
// and therefore always trapped in the Yii::$app->request->isAjax conditional

}


The above code all works fine and if I remove focus from the
$form->field($model, 'code')
field on my form, Yii's ajax validation kicks in and displays my custom error message based off of my custom validation logic.

My challenge arises when I go to submit the form. The form submission is also handled through ajax, and therefore the controller action always returns the result of the
ActiveForm::validate($model);
because
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post()))
will get apply to both the ajax form validation AND on the form submit.

With the above approach, I am forced to return only the results of the ajax validation and not any json data that I may need for additional client side validation, such as displaying the registration form after a valid use code is submitted through the ajax form.

I realize that I can set
'enableAjaxValidation' => false
on the ActiveForm and then return my own json data inside the
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post()))
condition. If I do this, I am able to show the registration form because I have my own json data to work with.

Is there a way to have ajax validation on a form that is submitted with ajax? How could you trap the ajax validation separately from the ajax form submission to handle the two events in different manners?

Any suggestions or alternate approaches are GREATLY appreciated!

Answer

You should set up validationUrl with a different URL compared to the URL that you are submitting the form to. In this way you can have the validation function that would validate and return the return ActiveForm::validate($model); and the normal submit form that does something else.

You can read more about validationUrl here: