Ajax posts validates twice

I have a form that looks like this

<?php 
                
                $form = ActiveForm::begin([
                    'id' => $model->formName(),
                    'enableAjaxValidation' => true,
                    'enableClientValidation'=> false,
                    'validateOnBlur' => false,
                    'validateOnChange' => false,
                    'validateOnSubmit' => true,
                    'options' => ['autocomplete' => 'off'],
                ]);
            ?>
...
...
...
<?php echo $form->field($model, 'captcha')->widget(\manchenkov\yii\recaptcha\ReCaptchaWidget::class, ['preloading' => true, 'showBadge' => (YII_DEBUG) ? true : false]); ?>

<?= Html::submitButton(Module::t('app', 'Calculate'), array('buttonType'=>'submit', 'class' => 'btn btn-lg')); ?>

<?php ActiveForm::end(); ?>

the JS

<script>
            $(document).ready(function () {  
                var $form = $("#<?= $model->formName() ?>");
                $form.on("submit", function (event, messages) {
                    event.preventDefault();
                    event.stopImmediatePropagation(); // this is required in some cases
                    $.ajax({
                        "type":"POST",
                        "url":$form.attr('action'),
                        "data":$form.serialize(),
                        "dataType":"json",
                        "cache": true, 
                        "success":function(data){
                            $("#t-tax").html(data.tax);	
                        }                    
                    });
                    return false;		
                });
            });
            </script>

when i submit the form, i noticed in my console the ajax post it called twice. Any idea what causes this or how to stop it from doing so? Thanks

Since you are writing your ajax validation JS on your own, you don’t need to set enableAjaxValidation for the ActiveForm.

                $form = ActiveForm::begin([
                    'id' => $model->formName(),
                    'enableAjaxValidation' => false,
                    'enableClientValidation'=> false,
                    'options' => ['autocomplete' => 'off'],
                ]);

thank you for the reply.

If i set it to false, the json response doesn’t highlight the input as red, and the error message doesn’t show under the input. here is my response.

calculator-tax [ "Tax cannot be blank." ]

my action looks like this

class calculatorAction extends Action
{
    public function run()
    {
                $model = new calculator;
		$model->scenario = calculator::SCENARIO_TAX;

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

			if ($model->validate())
			{
                             $this->calculatetax();
                             die;
			}
			else
		 	{
				Yii::$app->response->format = Response::FORMAT_JSON;
				return ActiveForm::validate($model);
			}

        } else {

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

ok, i made some changes to my javascript. Now it posts once. but the error messages dont show

$form.yiiActiveForm('updateMessages', data, true);

this doesn’t seem to display the error messages below the input, and doesn’t highlight the error input red too.

$(document).on("beforeSubmit", "#<?= $model->formName() ?>", function () {
                    var $form = $(this);
                    $.ajax({
                        "type":"POST",
                        "url":$form.attr('action'),
                        "data":$form.serialize(),
                        "dataType":"json",
                        "cache": true, 
                        "success":function(data){
                            $("#t-tax").html(data.t-tax);	
                        },                    
                    }).done(function(data) {
            if(data.success) {
                alert('ok');
            } else {
                $form.yiiActiveForm('updateMessages', data, true);
            }
        })
        .fail(function () {
            alert('request failed')
        })

                    return false; // Cancel form submitting.'

                }).on('submit', function(event){

event.preventDefault();
event.stopImmediatePropagation(); 

});

Why did you have to write your own javascript in the first place?

because i don’t want to post to another page and have that annoying browser resend warning when a user refreshed the page. So i used ajax to post, and the results will populate a <div>

"success":function(data){
    $("#t-tax").html(data.t-tax);	
}              

is there is a better or another way to do this, so i don’t have the resend warning on page refresh?

Usually you don’t need to write your own javascript to implement ajax validation of a form. You just need to set enableAjaxValidation to true for the active form.

As for the “resend warning” issue, why don’t you follow the Post/Recirect/Get (PRG) pattern ? (Gii’s CRUD generator would show you a good example.)

Post/Recirect/Get (PRG) pattern might not work for me. as i’m passing a lot of data back using ajax right now.