Yii Framework Forum: Form Validation With Ajaxsubmitbutton - Yii Framework Forum

Jump to content

  • (2 Pages)
  • +
  • 1
  • 2
  • You cannot start a new topic
  • You cannot reply to this topic

Form Validation With Ajaxsubmitbutton Showing validation errors of the form when using ajaxSubmitButton Rate Topic: ***** 3 Votes

#1 User is offline   riyazMuhammed 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 42
  • Joined: 13-September 12
  • Location:Bangalore

Posted 30 October 2012 - 06:31 AM

*
POPULAR

Hi I would like to share a simple tip to all those who still dint get a simple straight-forward method to show validation errors of the form which has a ajaxSubmitButton.

Step 1: @ your controller action

  public function actionMyAction()
	{       
		$model=new User;             
                $this->performAjaxValidation($model);  
                
		if(isset($_POST['User']))
		{
                        $model->attributes=$_POST['User'];
                        $valid=$model->validate();            
			if($valid){
                                          
                           //do anything here
                             echo CJSON::encode(array(
                                  'status'=>'success'
                             ));
                            Yii::app()->end();
                            }
                            else{
                                $error = CActiveForm::validate($model);
                                if($error!='[]')
                                    echo $error;
                                Yii::app()->end();
                            }
               }
     
	}




Step 2: @ your view
Your form may look like this

<?php
$form=$this->beginWidget('CActiveForm', array(
	'id'=>'user-form',
	'enableAjaxValidation'=>true,
        'action'=>$this->createUrl('myController/MyAction'),
        'enableClientValidation'=>true,
     
));
   ?>
        <div class="errorMessage" id="formResult"></div>
        <div id="AjaxLoader" style="display: none"><img src="<?php echo Yii::app()->request->baseUrl; ?>/images/spinner.gif"></img></div>
	<div class="row-user-single">
		<?php echo $form->labelEx($model,'attribute1'); ?>
		<?php echo $form->passwordField($model,'attribute1',array('size'=>60,'maxlength'=>500)); ?>
		<?php echo $form->error($model,'attribute1'); ?>
	</div>

	<div class="row-user-single">
		<?php echo $form->labelEx($model,'attribute2'); ?>
		<?php echo $form->passwordField($model,'attribute2',array('size'=>60,'maxlength'=>500)); ?>
		<?php echo $form->error($model,'attribute2'); ?>
	</div>
        <div class="buttons">
		
         <?php echo CHtml::ajaxSubmitButton('Save',CHtml::normalizeUrl(array('myController/MyAction','render'=>true)),
                 array(
                     'dataType'=>'json',
                     'type'=>'post',
                     'success'=>'function(data) {
                         $("#AjaxLoader").hide();  
                        if(data.status=="success"){
                         $("#formResult").html("form submitted successfully.");
                         $("#user-form")[0].reset();
                        }
                         else{
                        $.each(data, function(key, val) {
                        $("#user-form #"+key+"_em_").text(val);                                                    
                        $("#user-form #"+key+"_em_").show();
                        });
                        }       
                    }',                    
                     'beforeSend'=>'function(){                        
                           $("#AjaxLoader").show();
                      }'
                     ),array('id'=>'mybtn','class'=>'class1 class2')); ?>
<?php $this->endWidget();?>



This is working just fine for me :)
And all the code written above are my style of writing. You may change them as required but,
there are only two things to be noted as follows:
1. @ your controller call validate of your model and return a json object if form is invalid
2. @ your view break this json object (OR traverse through it) and show the error messages under respective elements of the form.

Keep it simple :)
7

#2 User is offline   sivam 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 1
  • Joined: 27-April 12

Posted 02 November 2012 - 01:49 AM

Hi Riyaz,

Thanks a lot for your valuable code...

SivaMurugan B.

0

#3 User is offline   bennouna 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,165
  • Joined: 05-January 12
  • Location:Morocco

Posted 02 November 2012 - 03:26 AM

Doesn't this line generate an error in case there are form errors ?

 if(data.status=="success"){

In case of errors you don't have data.status

Instead you should check if the first position of your data is {
0

#4 User is offline   riyazMuhammed 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 42
  • Joined: 13-September 12
  • Location:Bangalore

Posted 02 November 2012 - 05:00 AM

View Postsivam, on 02 November 2012 - 01:49 AM, said:

Hi Riyaz,

Thanks a lot for your valuable code...

SivaMurugan B.



You are welcome Sivam :)
And Welcome to the Yii family :)
0

#5 User is offline   riyazMuhammed 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 42
  • Joined: 13-September 12
  • Location:Bangalore

Posted 02 November 2012 - 05:10 AM

View Postbennouna, on 02 November 2012 - 03:26 AM, said:

Doesn't this line generate an error in case there are form errors ?

 if(data.status=="success"){

In case of errors you don't have data.status

Instead you should check if the first position of your data is {


Nope. It is not giving any error in any case :)
Tested many times before posting it in the forum buddy :)
And in both the cases, the json data starts from "{" . So I hope we shall not rely on "{".

Thanks a lot though :)
0

#6 User is offline   bennouna 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,165
  • Joined: 05-January 12
  • Location:Morocco

Posted 02 November 2012 - 05:15 AM

Quote

Nope. It is not giving any error in any case
Tested many times before posting it in the forum buddy
And in both the cases, the json data starts from "{" . So I hope we shall not rely on "{".

My bad you're totally right. In an ajax webapp, I returned a string or the json errors, so it was slightly different.
0

#7 User is offline   seenivasan 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 620
  • Joined: 17-June 12
  • Location:Chennai,TamilNadu,India.

Posted 28 December 2012 - 09:27 AM

*
POPULAR

Dear Friends.

I have made an attempt to make it simple.

Kindly check this.

I am not using CHtml::ajaxSubmitButton. Instead I am using normal CHtml::submitButton.

I am making the needed ajax call in afterValidate method of yiiActiveForm.js.


The following is one example.

<div class="form">

<?php $form=$this->beginWidget('CActiveForm', array(
	'id'=>'user-form',
	'enableAjaxValidation'=>true,
	'clientOptions'=>array(
	    'validateOnSubmit'=>true,
	    'afterValidate'=>'js:function(form,data,hasError){
			if(!hasError){
				$.ajax({
					"type":"POST",
					"url":"'.CHtml::normalizeUrl(array("test/eleven")).'",
					"data":form.serialize(),
					"success":function(data){$("#test").html(data);},
					
					});
				}
			}'
	),
)); ?>

	<p class="note">Fields with <span class="required">*</span> are required.</p>

	<?php echo $form->errorSummary($model); ?>

	<div class="row">
		<?php echo $form->labelEx($model,'username'); ?>
		<?php echo $form->textField($model,'username',array('size'=>60,'maxlength'=>64)); ?>
		<?php echo $form->error($model,'username'); ?>
	</div>

	<div class="row">
		<?php echo $form->labelEx($model,'age'); ?>
		<?php echo $form->textField($model,'age'); ?>
		<?php echo $form->error($model,'age'); ?>
	</div>

	<div class="row">
		<?php echo $form->labelEx($model,'email'); ?>
		<?php echo $form->textField($model,'email',array('size'=>60,'maxlength'=>128)); ?>
		<?php echo $form->error($model,'email'); ?>
	</div>

	<div class="row buttons">
		<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>
	</div>

<?php $this->endWidget(); ?>

</div><!-- form -->

<!-- AJAX update div element -->

<div id="test"></div>



Ajax is going to update the div element with id of "test".

"test/eleven"denotes my conrollerId and actionId in my case.

Upon submitting the form and if there is no validation error, normal submit action is discarded
and Ajax call only is being made.

Regards.
8

#8 User is offline   riyazMuhammed 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 42
  • Joined: 13-September 12
  • Location:Bangalore

Posted 07 March 2013 - 02:35 PM

Hi, thanks for sharing. When you need ajax and form submit together, we can directly use ajaxsubmitbutton rather than "button and writing seperate jquery ajax function". And how do you show error messages of the form straight from the model itself in your case ?

Please don't mind I m just curious to know the info, since I could not find anything as straight forward as my post for this kind of requirement :)
0

#9 User is offline   seenivasan 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 620
  • Joined: 17-June 12
  • Location:Chennai,TamilNadu,India.

Posted 16 March 2013 - 06:07 AM

Dear Friend

First I should appreciate you for sharing a very useful tip.

Regarding your apprehensions, I need to clarify with you on certain aspects of my code.

<?php $form=$this->beginWidget('CActiveForm', array(
        'id'=>'user-form',
        'enableAjaxValidation'=>true,
        'clientOptions'=>array(
            'validateOnSubmit'=>true,
            'afterValidate'=>'js:function(form,data,hasError){
                        if(!hasError){
                                $.ajax({
                                        "type":"POST",
                                        "url":"'.CHtml::normalizeUrl(array("test/eleven")).'",
                                        "data":form.serialize(),
                                        "success":function(data){$("#test").html(data);},
                                        
                                        });
                                }
                        }'
        ),
)); ?>



1.
'validateOnSubmit'=>true,

The above ensures that the form will not be submitted even there is a single error.

2.
 if(!hasError)

The above also ensures that the form will not be submitted by ajax enen there is single error.

Till the submission is error free, form will display errors.

Regards.
0

#10 User is offline   riyazMuhammed 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 42
  • Joined: 13-September 12
  • Location:Bangalore

Posted 18 March 2013 - 07:38 AM

Cool :)
Works too :)
0

#11 User is offline   yiqing95 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 585
  • Joined: 27-December 10
  • Location:china

Posted 04 April 2013 - 11:51 AM

nice solution! :lol:
really helpful !
0

#12 User is offline   bomber 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 4
  • Joined: 18-April 13

Posted 18 April 2013 - 03:15 AM

nice thanks!
0

#13 User is online   msoa 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 234
  • Joined: 15-August 12

Posted 22 April 2013 - 06:38 AM

here is my practice.
0

#14 User is offline   amanation 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 8
  • Joined: 16-May 13
  • Location:Nigeria

Posted 15 June 2013 - 06:35 PM

Thanks a lot riyazMuhammed and Seenivasan. Very helpful tips!!!
Yes we can!

Extension
ajaxuploader
0

#15 User is offline   este 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 41
  • Joined: 23-September 11

Posted 03 July 2013 - 07:30 PM

Just a little tip, if you want to make sure you get JSON data: add dataType: "json" in jquery ajax attributes.


function(form,data,hasError){
                        if(!hasError){
                                $.ajax({
                                        "type":"POST",
                                        "url": "/yourUrl/yours/",
                                        "data":form.serialize(),
                                        "dataType":"json",
                                        "success":function(data){
                                                console.log(data); // now this is a js object
                                                // You can get the number of errors like this in modern browsers:
                                                var errors = Object.keys(data).length;
                                                if (!errors) {
                                                    // form is ready to go (unless it is already gone, depending on your controller)
                                                }
                                            },
                                        });
                                }
                        }'

0

#16 User is offline   adoming3 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 19
  • Joined: 31-July 12

Posted 05 August 2013 - 11:18 PM

Great topic! I haven't seen anyone cover this so well. Thank you.
0

#17 User is offline   mplexus 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 5
  • Joined: 19-March 13
  • Location:Greece

Posted 14 August 2013 - 09:36 AM

Nice solution!

In my case I had to change some things in the view like parsing the JSON object and clearing any error divs
$(".errorMessage").text("");$(".errorMessage").hide();
if a future ajax call was successfull.

'success'=>'function(data){
                                                $("#statusMsg").html("");
                                                var obj = $.parseJSON(data);
                                                if(obj.status == "success"){
                                                    $(".errorMessage").text("");
                                                    $(".errorMessage").hide();
                                                    $("#recentId").html(obj.id);
                                                    $("#statusMsg").html(obj.msg);
                                                    $("#statusMsg").show();
                                                    $("#statusMsg").delay(3000).fadeOut("slow");
                                                    /*$("#expenses-grid").yiiGridView("update");*/
                                                    $("#enableSubmitButton").trigger("click");
                                                }else{
                                                    $("#recentId").html(obj.id);
                                                    $("#statusMsg").html(obj.msg);
                                                    $("#statusMsg").show();
                                                    $.each(obj.errors, function(key, val) {
                                                        $("#expenses-form #"+key+"_em_").text(val);                                                    
                                                        $("#expenses-form #"+key+"_em_").show();
                                                    });
                                                }
                                             }'

0

#18 User is offline   Dmitry Zhukov 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 1
  • Joined: 02-October 13

Posted 03 October 2013 - 03:39 PM

I wanted to share here my solution to the problem. Here is the js function that can be called to validate any CActiveForm.
var validateYiiForm = function(form, success, failure) {
	var $form = $(form);
	var settings = $form.data('settings');
	settings.submitting = true;
	$.fn.yiiactiveform.validate($form, function (data) {
		var hasError = false;
		$.each(settings.attributes, function () {
			hasError = $.fn.yiiactiveform.updateInput(this, data, $form) || hasError;
		});
		$.fn.yiiactiveform.updateSummary($form, data);
		settings.submitting = false;
		if (hasError) {
			failure === undefined || failure(data);
		} else {
			success === undefined || success(data);
		}
	});
};


You can use it this way:
$('#submit_button_id').bind('click', function() {
  validateYiiForm(
    '#form_id', 
    function(data) {
      // the form is valid, data parameter should be empty
      $.ajax({
        // whatever code you use to submit your form
      })
    },
    function(data) {
      // failed to validate
      // validation messages are shown in appropriate divs
      // data argument contains json with validation errors 
    }
  )
});

It's strait forward to make your own ajaxSubmitButton using this function.

Have a good time!
0

#19 User is offline   bmadeiro 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 5
  • Joined: 30-June 09

Posted 15 October 2013 - 12:09 PM

This is my solution, based on riyazMuhammed solution and others.

In my applications always need return messages.

In Controller:


    public function actionCreate()
    {
        $model = new User;

        if (isset($_POST['User']))
        {
            $model->attributes = $_POST['User'];
            
            try
            {
                $error = CActiveForm::validate($model);
                
                if ($error == '[]')
                    //No errors
                    $model->save();
                else
                    //Return messages from form validation
                    echo $error;
            }
            catch (Exception $e)
            {
                //Return messages from try/catch
                echo CJSON::encode(array(
                    'status' => 'error',
                    'msg' => $e->getMessage()
                ));
            }
        }
        else
            $this->render('create', array(
                'model' => $model,
            ));
    }


In View:

//CREATE
if ($model->isNewRecord)
{
    //CONFIRM
    $js = "if (confirm('Success. Do you like insert another?')) {
        form[0].reset();
    }
    else
        //REDIRECT to INDEX
        location.href = '{$this->createUrl('user/index')}';
    ";
}
//UPDATE
else
{
    $js = "alert('Updated!');
        location.href = '{$this->createUrl('user/index')}';";
}

//BOOTSTRAP ACTIVEFORM
$form = $this->beginWidget('bootstrap.widgets.TbActiveForm', array(
    'id' => 'user-form',
    'layout' => TbHtml::FORM_LAYOUT_INLINE,
    'enableAjaxValidation' => true,
    //VERY IMPORTANT        
    'enableClientValidation' => false,
    'focus' => 'input:text:enabled:visible:first',
    'clientOptions' => array(
        'validateOnSubmit' => true,
        'validateOnChange' => false,
        'validateOnType' => false,
        //Receive and show return messages
        'afterValidate' => "js:function(form, data, hasError){
            //RECEIVE FORM VALIDATION MESSAGES
            if (hasError) {

                //DO SOMETHING IF NECESSARY
                return false;
            }
            //RECEIVE other validation messages from try/catch: database constraints, unknown messages
            else {
                //SHOW MESSAGES
                if (typeof data.status !== 'undefined')
                    alert(data.msg);
                //NO ERROR, DO SOMETHING (SHOW ABOVE CONDITIONS)
                else {
                    " . $js . "
                }
            }
        }"
    ),
));



In this way CActiveForm do everything. I don't need ajax submit buttons and parse the JSON object to show error messages.

[]'s
0

#20 Guest_Interboy_*

  • Group: Guests

Posted 22 October 2013 - 10:10 PM

I add more example:

Yii client-side form validation before ajax submition

A time ago i've met the issue that Yii doesn't run any client-side form validation when submitting the form by CHtml::ajaxSubmitButton. The small javascript below helps to fix it.


/*
1) Register the snippet into the HEAD. Be sure that it is linked after jquery.yii.js is linked.
 
2) Configure your CActiveForm instance like this:
*/
 
$this->beginWidget('CActiveForm', array(
    ...
    'enableClientValidation'=>true,
    'clientOptions'=>array(
        'validateOnSubmit'=>true,
        'afterValidate'=>'js:$.yii.fix.ajaxSubmit.afterValidate'
    )
    ...
);
/*
3) Configure your CHtml::ajaxSubmitButton instance like this:
*/
 
echo CHtml::ajaxSubmitButton('Whateverlabel', 'whateverurl', array(
    ...
    'beforeSend'=>'js:$.yii.fix.ajaxSubmit.beforeSend("#YOUR_FORM_ID")'
    ...
);

0

Share this topic:


  • (2 Pages)
  • +
  • 1
  • 2
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users