Je me demande si des experts en Yii2 peuvent m'aider à comprendre comment utiliser au mieux les formulaires ajax associés à la validation Yii ajax. Je pense que je peux expliquer le problème sans vous faire parcourir tout mon code.
Je travaille sur un formulaire de saisie de code promotionnel où l'utilisateur entre son code promotionnel dans le formulaire, le formulaire est envoyé via ajax. Nous effectuons ensuite une recherche dans la base de données pour connaître les détails du code promo, le validons et si le code est validé, nous souhaitons afficher le formulaire d'inscription masqué sur la page.
J'ai une fonction de validation personnalisée pour le champ de formulaire "code", qui est le champ actif dans un scénario de modèle nommé "registre".
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.');
}
}
...
}
Ensuite, dans le contrôleur, comme suggéré par le Guide Yii2, je piège cette validation ajax avec le code suivant:
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
}
Le code ci-dessus fonctionne bien et si je supprime le focus du champ $form->field($model, 'code')
de mon formulaire, la validation ajax de Yii démarre et affiche mon message d'erreur personnalisé basé sur ma logique de validation personnalisée.
Mon défi se pose lorsque je vais soumettre le formulaire. La soumission de formulaire est également traitée via ajax, et par conséquent, l'action du contrôleur renvoie toujours le résultat de ActiveForm::validate($model);
car if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post()))
sera appliqué à la fois à la validation de formulaire ajax ET au formulaire de soumission.
Avec l'approche ci-dessus, je suis obligé de ne renvoyer que les résultats de la validation ajax et non les données json dont j'ai besoin pour une validation supplémentaire côté client, telles que l'affichage du formulaire d'inscription après qu'un code d'utilisation valide est soumis via le formulaire ajax.
Je me rends compte que je peux définir 'enableAjaxValidation' => false
sur ActiveForm, puis renvoyer mes propres données json dans la condition if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post()))
. Si je le fais, je pourrai afficher le formulaire d’inscription car je dispose de mes propres données JSON.
Existe-t-il un moyen de valider ajax sur un formulaire soumis avec ajax? Comment pouvez-vous intercepter la validation ajax séparément de la soumission de formulaire ajax pour gérer les deux événements de manières différentes?
Toutes les suggestions ou approches alternatives sont grandement appréciées!
Vous devez configurer validationUrl
avec une URL différente de celle à laquelle vous envoyez le formulaire. De cette façon, vous pouvez avoir la fonction de validation qui validerait et renverrait la return ActiveForm::validate($model);
et le formulaire de soumission normal qui fait autre chose.
Vous pouvez en savoir plus sur validationUrl
ici :
J'ai trouvé une solution:
Forme :
<?php
$form = ActiveForm::begin(['id' => 'form-add-contact', 'enableAjaxValidation' => true, 'validationUrl' => Yii::$app->urlManager->createUrl('contacts/contacts/contact-validate')]);
?>
Soumettre via Ajax:
<?php
$script = <<< JS
$(document).ready(function () {
$("#form-add-contact").on('beforeSubmit', function (event) {
event.preventDefault();
var form_data = new FormData($('#form-add-contact')[0]);
$.ajax({
url: $("#form-add-contact").attr('action'),
dataType: 'JSON',
cache: false,
contentType: false,
processData: false,
data: form_data, //$(this).serialize(),
type: 'post',
beforeSend: function() {
},
success: function(response){
toastr.success("",response.message);
},
complete: function() {
},
error: function (data) {
toastr.warning("","There may a error on uploading. Try again later");
}
});
return false;
});
});
JS;
$this->registerJs($script);
?>
Manette :
/*
* CREATE CONTACT FORM AJAX VALIDATION ACTION
*/
public function actionContactValidate() {
$model = new ContactsManagement();
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
$model->company_id = Yii::$app->user->identity->company_id;
$model->created_at = time();
\Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
}
/**
* Quick Add Contact Action
* @param type $id
* @return type
*/
public function actionAddContact() {
$model = new ContactsManagement();
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
$transaction = \Yii::$app->db->beginTransaction();
try {
if ($model->validate()) {
$flag = $model->save(false);
if ($flag == true) {
$transaction->commit();
return Json::encode(array( 'status' => 'success', 'type' => 'success', 'message' => 'Contact created successfully.'));
} else {
$transaction->rollBack();
}
} else {
return Json::encode(array('status' => 'warning', 'type' => 'warning', 'message' => 'Contact can not created.'));
}
} catch (Exception $ex) {
$transaction->rollBack();
}
}
return $this->renderAjax('_add_form', [
'model' => $model,
]);
}