AJAX form submission with server validation

hi all,
i try to comprehend of using YII2 cookbook - AJAX form submission with server validation, i already install fresh yii2 basic via composer, and add the code guide, here the code :

use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use yii\captcha\Captcha;

$this->title = 'Contact';
$this->params['breadcrumbs'][] = $this->title;
<div class="site-contact">
    <h1><?= Html::encode($this->title) ?></h1>
    <?php if (Yii::$app->session->hasFlash('contactFormSubmitted')): ?>
        <div class="alert alert-success">
            Thank you for contacting us. We will respond to you as soon as possible.
    <?php else: ?>
        <div class="row">
            <div class="col-lg-5">
                <?php $form = ActiveForm::begin(['id' => 'contact-form']); ?>
                    <?= $form->field($model, 'name')->textInput(['autofocus' => true]) ?>
                    <?= $form->field($model, 'email') ?>
                    <?= $form->field($model, 'subject') ?>
                    <?= $form->field($model, 'body')->textarea(['rows' => 6]) ?>
                    <?= $form->field($model, 'verifyCode')->widget(Captcha::className(), [
                        'template' => '<div class="row"><div class="col-lg-3">{image}</div><div class="col-lg-6">{input}</div></div>',
                    ]) ?>
                    <div class="form-group">
                        <?= Html::submitButton('Submit', ['class' => 'btn btn-primary', 'name' => 'contact-button']) ?>
                <?php ActiveForm::end(); ?>
    <?php endif; ?>


public function actionContact()
$model = new ContactForm();
if ($model->load(Yii::$app->request->post()) && $model->contact(Yii::$app->params[‘adminEmail’])) {

    return $this->refresh();
return $this->render('contact', [
    'model' => $model,


#here the code from cookbook i added in SiteController.php
public function actionUpdate($id)
$model = $this->findModel($id);

    if (Yii::$app->request->isAjax) {
        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->asJson(['success' => true]);

        $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;

        return $this->asJson(['validation' => $result]);

    return $this->render('update', [
        'model' => $model,

#here the ajax handler in views/layouts/main.php

<?php $this->endBody() ?>
$('#contact-form').on('beforeSubmit', function () {
    var $yiiform = $(this);
            type: $yiiform.attr('method'),
            url: $yiiform.attr('action'),
            data: $yiiform.serializeArray(),
        .done(function(data) {
            if(data.success) {
                // data is saved
            } else if (data.validation) {
                // server validation failed
                $yiiform.yiiActiveForm('updateMessages', data.validation, true); // renders validation messages at appropriate places
            } else {
                // incorrect server response
        .fail(function () {
            // request failed

    return false; // prevent default form submission
<?php $this->endPage() ?>

#here the models/ContactForm.php

namespace app\models;

use Yii;
use yii\base\Model;

class ContactForm extends Model
    public $name;
    public $email;
    public $subject;
    public $body;
    public $verifyCode;

     * @return array the validation rules.
    public function rules()
        return [
            // name, email, subject and body are required
            [['name', 'email', 'subject', 'body'], 'required'],
            // email has to be a valid email address
            ['email', 'email'],
            // verifyCode needs to be entered correctly
            ['verifyCode', 'captcha'],

     * @return array customized attribute labels
    public function attributeLabels()
        return [
            'verifyCode' => 'Verification Code',

     * Sends an email to the specified email address using the information collected by this model.
     * @param string $email the target email address
     * @return bool whether the model passes validation
    public function contact($email)
        if ($this->validate()) {
                ->setFrom([$this->email => $this->name])

            return true;
        return false;

when i go to index.php?r=site/contact, there is nothing different, no error, alert-success show up. when i try debug the ajax code, its seem it go to .fail(function () {alert(‘why?’);}
maybe i missing something and really confuse what is going on(soory i’m so noob),
where is $this->render(‘update’, [
‘model’ => $model
do i need create that?

sincerely, thanks in advance

Not sure my answer is what you are look for, but after scrolling down all those lines in order to just submit a form via ajax, maybe you sould use the Pjax Widget instead, this allows you to do the same with only “two” lines of code.

Active Form
Active Form End

(You will find the correct code example trough googling)

Thanks u @nadario, is pjax can use yii2 activeform already built in js validation? I see many people using pjax or jquery, rarely using sample like cookbook above, can pjax compatible with kartik?

As Pjax integration is part of Yii 2 Framework, this should also work with other extensions. But i never used kartik extensions.

is pjax can use yii2 activeform already built in js validation?

I dont understand the question.

Validation works on client side and on server side out of the box.

as mention in cookbook :
In order to be compatible with third party widgets like (Kartik), the best option to retrieve the actual value of an attribute is:

$('#form_id').yiiActiveForm('find', 'attribute').value

since i will use kartik