About CActiveForm in document is:(clientOptions section)
ajaxVar: string, the name of the parameter indicating the request is an AJAX request. When the AJAX validation is triggered, a parameter named as this property will be sent together with the other form data to the server. The parameter value is the form ID. The server side can then detect who triggers the AJAX validation and react accordingly. Defaults to 'ajax'.
Now take a look in my example:
Summary: i have a form with two fields mail and newEmail, i submitted form via ajaxSubmitButton(if you need form code tell me put it). In following i get var_dump($_POST) content in two state:
First: Following var_dump($_POST) is for when a field(newEmail) is left empty:
array
'User' =>
array
'email' => string 'user#gmail.com' (length=14)
'newEmail' => string '' (length=0)
Second: Following var_dump($_POST) is for when all the fields are filled:
array
'User' =>
array
'email' => string 'user#gmail.com' (length=14)
'newEmail' => string 'admin#gmail.net' (length=19)
'ajax' => string 'email-form' (length=10)
'yt0' => string 'update' (length=18)
As you see only when all fields are filled the ajaxVar(ajax) exist in $_POST. When ajaxVar(ajax) initialized in CActiveForm?
Edit
email-form:
<?php
<div class="form">
<?php $form = $this->beginWidget('CActiveForm',array(
'id'=>'email-form',
'enableAjaxValidation'=>true,
'clientOptions'=>array(
'validateOnSubmit'=>true,
'focus'=>'input[type="email"]:first',
)
)); ?>
<div class="row">
<?php echo $form->label($model,'email') ?>
<?php echo $form->textField($model,'email') ?>
<?php echo $form->error($model,'email') ?>
</div>
<div class="row">
<?php echo $form->label($model,'newEmail') ?>
<?php echo $form->textField($model,'newEmail') ?>
<?php echo $form->error($model,'newEmail') ?>
</div>
<hr>
<div class="row">
<?php echo CHtml::ajaxSubmitButton(
'update',
Yii::app()->createUrl('upanel/user/CEmail'),
array(
'dataType'=>'json',
'type' => 'POST',
'data' => "js:$('#email-form').serialize()",
'success'=>'function(data){
if(data.status=="success")
{
//alert(data.status);
hideFormErrors(form="#email-form");
callback(status=data.status);
}else{
formErrors(data,form="#email-form");
}
}',
'beforeSend'=>'before',
),
array(
'id' => 'update-button'.uniqid(),
'class'=>'submit-button'
)
);
?>
</div>
<?php $this->endWidget() ?>
</div>
<?php echo $form->errorSummary($model,'please solve following errors:') ?>
actionCEmail:
public function actionCEmail()
{
/*ob_start();
var_dump($_POST);
$log=ob_get_contents();
$fp = fopen('data.html', 'w');
fwrite($fp, $log);
fclose($fp);
Yii::app()->end();*/ //This block active whenever i want see the $_POST content
$model = $this->loadModel(Yii::app()->user->id);
$model->scenario = 'CEmail';
$this->performAjaxValidation($model,'email-form');
if(Yii::app()->request->isAjaxRequest)
$this->renderPartial('_cemail',array('model'=>$model),false,true);
else
$this->render('update',array('model'=>$model,'form'=>'_cemail'));
}
protected function performAjaxValidation($model,$form)
{
if(isset($_POST['ajax']) && $_POST['ajax']===$form)
{
echo CActiveForm::validate($model);
Yii::app()->end();
}
}
ajaxVar
initialized onsubmit if 'validateOnSubmit'=>true,. Try to use validateOnChange=>true and show your cactiveform code when init it.
And really stop invent "a bycicle".
Try to read http://learnyii.blogspot.com/2010/12/yii.html if you didnt understand my code in previous question.
I showed you working code of ajax validation which i use on working project. And with that method your $_POST will update on change of all fields with JSON object wich will contain errors for form.
Stop flooding community. Regards.
In your action:
public function actionCEmail()
{
$model = $this->loadModel(Yii::app()->user->id);
$model->scenario = 'CEmail';
if(Yii::app()->request->isAjaxRequest)
{
$error = CActiveForm::validate($model);
if($error!='[]')
{
echo $error;
Yii::app()->end();
}
}
if(isset($_POST['CEmailForm']))
{
//put form name in POST above
//do whatever you need with model here
//save / edit etc.
//in the end
echo CJSON::encode(array(
'status'=>'success',
));
Yii::app()->end();
}
if(Yii::app()->request->isAjaxRequest) //check renders
$this->renderPartial('_cemail',array('model'=>$model),false,true);
else
$this->render('update',array('model'=>$model,'form'=>'_cemail'));
}
In your view submit button:
<?php echo CHtml::ajaxSubmitButton ("Save", Yii::app()->request->url, array (
'dataType' => 'json',
'type'=>'post',
'success' =>
'js:function (data) {
if(data.status=="success"){
//do whatever you need on success
//show flash/notification
};
}
else {//show errors here
$.each(data, function(key, val) {
$("#YourFormIDhere #"+key+"_em_").text(val);
$("#YourFormIDhere #"+key+"_em_").css(\'display\',\'block\');
});
//can show error summarry here or custom notifications
};
}',
), array (
'id' => 'yourbuttonid_submit_'.rand(1,255), // Need a unique id or they start to conflict with more than one load.
));?>
Try to do like this. It works. Keep it simple. You lost 2? days to validation of 2 fields.
I just made this on my changepassword form. It took me 5 minutes.
My post when trying to save with default empty field:
{"UserChangePassword_verifyPassword":["Required field","Retype Password is incorrect."]}
Make like this and dont loose time. Regards.
Related
I have the following view named 'findreseller.php':
<?php
$countries = CHtml::listData(Country::model()->findAll(), 'id', 'name');
echo CHtml::dropdownlist('find_reseller', '', $countries,
array('ajax'=>array(
'type'=>'POST',
'url'=>Yii::app()->getController()->createAbsoluteUrl('/webcare/reseller/loadAjaxData'),
'update' =>'#data',
)
)
);
?>
<div id="data">
<?php $this->renderPartial('_ajaxContent', array('dataProvider'=>$dataProvider))?>
</div>
_ajaxContent just echoes the result, nothing special there...
The dropdown, as you can see is generated with CHtml because I dont't need a form. I just need an onChange event to do something...
As per the code that follows, in '/webcare/reseller/loadAjaxData' I have:
public function actionLoadAjaxData() {
$country = $_POST['find_reseller'];
//do something...
$dataProvider=new CArrayDataProvider($country_reseller);
$this->render('findreseller', array('dataProvider' => $dataProvider));
}
I can tell that I am missing something, but I am not sure what exactly.
Edit
Modified like this:
<?php
//CHtml::form();
$countries = CHtml::listData(Country::model()->findAll(), 'id', 'name');
echo CHtml::dropdownlist('find_reseller', '', $countries,
array(
'ajax' => array(
'type'=>'POST', //request type
'url'=>CController::createUrl('/webcare/reseller/loadAjaxData'), //url to call.
//Style: CController::createUrl('currentController/methodToCall')
'update'=>'#city_id', //selector to update
'data'=>'js: $(this).val()',
//leave out the data key to pass all form values through
)
)
);
//empty since it will be filled by the other dropdown
echo CHtml::dropDownList('city_id','', array());
//CHtml::endForm();
?>
<div id="data">
<?php $this->renderPartial('_ajaxContent', array('dataProvider'=>$dataProvider))?>
</div>
And now I get:
http://prntscr.com/42wwx6
And I have the following controller action:
public function actionLoadAjaxData() {
$country = $_POST['country_id'];
...
$dataProvider=new CArrayDataProvider($country_reseller);
$data = User::model()->findAll('country_id=:country_id AND reseller=:reseller',
array(':country_id'=>(int) $_POST['country_id'], ':reseller'=>1));
$data=CHtml::listData($data,'city','city');
foreach($data as $value=>$name)
{
echo CHtml::tag('option',
array('value'=>$value),CHtml::encode($name),true);
}
$this->render('action_name', array('dataProvider' => $dataProvider));
}
Edit 2
If I write a die in actionLoadAjaxData(), right at the beginning, the method is loaded fine, the action is ok and the server answers 200.
[SOLVED :: Updated the CODE ] There is a drop down list and a text filed. Text filed will be filled per drop down selection by Ajax in Yii form. And I need to pass parameter to controller via Ajax URL. It is working when I pass static parameter via URL. But failed to get the dynamic parameter.
My Form::
<div class="row">
<?php echo $form->labelEx($model,'pp_store'); ?>
<?php // echo $form->dropDownlist($model,'pp_store', CHtml::listData(Branchmaster::model()->findAll(), 'cm_branch', 'cm_branch')); ?>
<?php $storeArray = CHtml::listData(Branchmaster::model()->findAll(),'cm_branch','cm_branch');
echo $form->dropDownList($model,'pp_store', $storeArray,
array(
'empty'=>"Select Warehouse",
'ajax' => array(
'type'=>'POST',
'url'=>CController::createUrl('purchaseordhd/GetCurrency' ),
'update' => '#currencyid',
'data'=>array('store'=>'js:this.value',),
'success'=> 'function(data) {$("#currencyid").empty();
$("#currencyid").val(data);
} ',
),
)); ?>
<?php echo $form->error($model,'pp_store'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'pp_currency'); ?>
<?php echo $form->textField($model,'pp_currency', array('id'=>'currencyid', 'readonly'=> true)); ?>
<?php echo $form->error($model,'pp_currency'); ?>
</div>
My Controller::
public function actionGetCurrency()
{
$q = $_POST['store'];
$sql = "SELECT cm_currency as value FROM cm_branchmaster WHERE cm_branch= '$q' ";
$command = Yii::app()->db->createCommand($sql);
$result= $command->queryScalar();
echo $result;
}
When I send parameter from Ajax URl "array('pp_store'=>'333')" then it is working well. But I need to send data dynamically.
[SOLVED :: Updated the CODE ] Enjoy Coding
You don't want to pass the parameter as per below example. Current element value will be taken as parameter to controller through POST.
http://www.yiiframework.com/wiki/24/creating-a-dependent-dropdown/
echo CHtml::dropDownList('country_id','', array(1=>'USA',2=>'France',3=>'Japan'),
array(
'ajax' => array(
'type'=>'POST', //request type
'url'=>CController::createUrl('currentController/dynamiccities'), //url to call.
//Style: CController::createUrl('currentController/methodToCall')
'update'=>'#city_id', //selector to update
//'data'=>'js:javascript statement'
//leave out the data key to pass all form values through
)));
//empty since it will be filled by the other dropdown
echo CHtml::dropDownList('city_id','', array());
If you want to send data manually, then you have to uncomment the 'data'=>'js:javascript statement'.
First post here on stack overflow so I hope I do it right, I have searched but cannot find what I am looking for.
i am new to cakephp and fairly new to php. I was able to get up and running yesterday no problem and can send data to my database. to day I wanted to work on validation with ajax but I think I am going to leave the ajax out of it for a little while as I have a problem with the validation errors displaying.
The validation is set up for the first two form fields like this;
<?php
class people extends AppModel
{
public $name = 'people';
public $useTable = 'people';
public $validate = array(
'firstName'=>array(
'rule'=>'notEmpty',
'message'=>'Enter You First Name'
),
'secondName'=>array(
'rule'=>'notEmpty',
'message'=>'Enter Your Second/Family Name'
),
);
}?>
and it works fine if those fields are empty it wont write to the database so far so good. However, when I hit submit on the form the page refreshes, the error messages appear under the form fields but it also adds a completely new form under the previous one. here is the controller. Note: the validate_form function is from an cakephp with ajax tutorial i was following and is commented out
<?php
class peoplesController extends AppController
{
public $name = "peoples";
public $helpers = array('Html', 'form', 'Js');
public $components = array('RequestHandler');
public function index() {
if( $this->request->is('post'))
{
$data = $this->request->data;
$this->people->save($data);
}
}
/*public function validate_form() {
if ($this->RequestHandler->isAjax()) {
$this->data['people'][$this->params['form']['field']] = $this->params['form']['value'];
$this->people->set($this->data);
if ($this->people->validates()) {
$this->autoRender = FALSE;
}
else {
$error = $this->validateErrors($this->people);
$this->set('error', $error[$this->params['form']['field']]);
}
}
}*/
}
?>
and the view. note: the divs with id sending and success are also from the tutorial I was following but I dont think would have an effect on this particular issue.
<div id="success"></div>
<h2> Fill in your profile details </h2>
<?php
echo $this->Form->create('people');
echo $this->Form->input('firstName');
echo $this->Form->input('secondName');
echo $this->Form->input('addressOne');
echo $this->Form->input('addressTwo');
echo $this->Form->input('city');
echo $this->Form->input('county');
echo $this->Form->input('country');
echo $this->Form->input('postCode', array(
'label' => 'Zip Code',
));
echo $this->Form->input('dob', array(
'label' => 'Date of birth',
'dateFormat' => 'DMY',
'minYear' => date('Y') - 70,
'maxYear' => date('Y') - 18,
));
echo $this->Form->input('homePhone');
echo $this->Form->input('mobilePhone');
echo $this->Form->input('email', array(
'type' => 'email'
));
$goptions = array(1 => 'Male', 2 => 'Female');
$gattributes = array('legend' => false);
echo $this->Form->radio('gender',
$goptions, $gattributes
);
echo $this->Form->input('weight');
echo $this->Form->input('height');
$toptions = array(1 => 'Tandem', 2 => 'Solo');
$tattributes = array('legend' => false);
echo $this->Form->radio('trained',
$toptions, $tattributes
);
echo $this->Form->input('referedBy');
/*echo $this->Form->submit('submit');*/
echo $this->Js->submit('Send', array(
'before'=>$this->Js->get('#sending')->effect('fadeIn'),
'success'=>$this->Js->get('#sending')->effect('fadeOut'),
'update'=>'#success'
));
echo $this->Form->end();
?>
<div id="sending" style="display: none; background-color: lightgreen">Sending.... </div>
<?php
echo $this->Html->script(
'validation', FALSE);
?>
so the creation of the second identical form on the same page is my primary problem, I think it has something to do with the controller taking the first form and sending it back to the same view but I dont know how to trouble shoot this.
a second problem is that for some reason if I use
echo $this->Form->submit('submit');
instead of
echo $this->Js->submit('send', array(
'before'=>$this->Js->get('#sending')->effect('fadeIn'),
'success'=>$this->Js->get('sending')->effect('fadeOut'),
'update'=>'#success'));
Then I dont get my error messages anymore I instead just get a bubble that appears and says 'please fill in this field' I am sure this is a jquery issue but again I dont know how to trouble shoot it so that that bullbe does not appear and it instead shows the error messages I want
Thanks in advance
Couple things:
1) Use Caps for your classnames. So People, PeoplesController, etc
2) Don't mess with Ajax until you get the standard flow working. So go back to $this->Form->submit('submit');.
3) That "required" tooltip is HTML5. Since you set the validation to notEmpty, Cake adds HTML5 markup to make the field required. Modify your Form->create call to bypass that for now (if you need to, but it provides client-side validation which is more efficient):
$this->Form->create('People', array('novalidate' => true));
See the FormHelper docs for more info on HTML5 validations
There is two actions in the controller:
CProfile:
public function actionCProfile()
{
$model=$this->loadModel(Yii::app()->user->id);
$model->scenario = 'updateProfile';
$this->performAjaxValidation($model);
if(isset($_POST['User'])){
$model->attributes=$_POST['User'];
if($model->validate())
if($model->save()){
if(Yii::app()->request->isAjaxRequest)
Yii::app()->end('saved');
else{
Yii::app()->user->setFlash('status','saved');
}
}
if(Yii::app()->request->isAjaxRequest)
if(!$model->validate())
Yii::app()->end('!validate');
}
if(Yii::app()->request->isAjaxRequest)
$this->renderPartial('_cprofile',array('model'=>$model));
else
$this->render('update',array('model'=>$model,'form'=>'_cprofile'));
}
And CPass:
public function actionCPass()
{
$model = $this->loadModel(Yii::app()->user->id);
$model->scenario = 'CPass';
$this->performAjaxValidation($model);
if(isset($_POST['User'])){
$model->attributes = $_POST['User'];
if($model->validate()){
if($model->verifyPassword($model->currentPass)){
$model->changePassword($model->newPass);
Yii::app()->end('changed');
}
}
}
if(Yii::app()->request->isAjaxRequest)
$this->renderPartial('_cpass',array('model'=>$model));
else
$this->render('update',array('model'=>$model,'form'=>'_cpass'));
}
And three view files:
update.php:
<?php
$cs = Yii::app()->clientScript;
$cs->registerCssFile('/x/css/myDetailview.css');
$cs->registerCssFile('/x/css/upanel/user-profile.css');
$url = Yii::app()->getBaseUrl().'/js/upanel.js';
$cs->registerScriptFile($url,CClientScript::POS_HEAD);
?>
<div id='user-profile-menu'>
<ul>
<li><?php echo CHtml::link('profile',Yii::app()->createUrl('/upanel/user/CProfile'),array('id'=>'profile-change-link')) ?></li>
<li><?php echo CHtml::link('change email',Yii::app()->createUrl('/upanel/user/CPass'),array('id'=>'pass-change-link')) ?></li>
</ul>
</div>
<div id='container'>
<?php $this->renderPartial($form,array('model'=>$model)); ?>
</div>
_cprofile.php:
<div class="form" >
<?php
$form = $this->beginWidget('CActiveForm',array(
'id'=>'change-profile-form',
'enableAjaxValidation'=>true,
'enableClientValidation'=>true,
'action' => 'index.php?r=upanel/user/cprofile',
'method' => 'post',
'clientOptions'=>array(
'validateOnSubmit'=>true,
'validateOnChange'=>true,
'validateOnType'=>false,
),
));
?>
.
.
.
<div class="row">
<?php
$url=Yii::app()->createUrl('upanel/user/CProfile');
echo CHtml::ajaxSubmitButton('update',$url,
array(
'type'=>'POST',
'data'=>"js:$('#change-profile-form').serialize()",
'success'=>'callback',
'beforeSend'=>'before',
),
array(
'id'=>'update-button',
'class'=>'submit-button',
)
);
?>
</div>
<?php $this->endWidget() ?>
<?php echo $form->errorSummary($model,'resolve following errors: ') ?>
_cpass.php:
<div class="form">
<?php
$form = $this->beginWidget('CActiveForm',array(
'id'=>'change-pass-form',
'enableAjaxValidation' => 'true',
'action' => Yii::app()->createUrl('upanel/user/CPass'),
'method' => 'POST',
'clientOptions' => array(
'validateOnSubmit' => true,
'validateOnChange' => true,
'validateOnType' => false,
)
));
?>
.
.
.
<div class="row">
<?php
$url=Yii::app()->createUrl('upanel/user/CPass');
echo CHtml::ajaxSubmitButton('update',$url,
array(
'type'=>'POST',
'data'=>"js:$('#change-pass-form').serialize()",
'success'=>'callback',
'beforeSend'=>'before',
),
array(
'id'=>'update-button',
'class'=>'submit-button',
)
);
?>
</div>
<?php $this->endWidget() ?>
</div> <!-- End Password Form -->
<?php echo $form->errorSummary($model) ?>
*Edit #1: *
See, i have a view page named update.php that in this page there is two links:
<div id='user-profile-menu'>
<ul>
<li><?php echo CHtml::link('profile',Yii::app()->createUrl('/upanel/user/CProfile'),array('id'=>'profile-change-link')) ?></li>
<li><?php echo CHtml::link('Change Password',Yii::app()->createUrl('/upanel/user/CPass'),array('id'=>'pass-change-link')) ?></li>
</ul>
The following JQuery code runs exsist actions in controller, that result is a renderpartial() one of these view files: _cpass.php or _profile.php
$('document').ready(function(){
$('#profile-change-link').click(function(){
var link = $(this).attr('href');
$('#container').load(link);
return false;
})
$('#pass-change-link').click(function(){
var link = $(this).attr('href');
$('#container').load(link);
return false;
})
});
In the controller CProfile action defined as default action. with this action there is no any problem in which of POST and Ajax methods.
But main problem: after that _cpass.php view replaced with _profile and have send the exist form in the _profile to CPass action for processing encountered with problem.
The problem is this:
Output of following code as expected is 1:
public function actionCPass()
{
$model = $this->loadModel(Yii::app()->user->id);
$model->scenario = 'CPass';
$this->performAjaxValidation($model);
if (1==1)
Yii::app()->end('1');
}
But output of following code is not that thing we expected. Returned value is a renderpartial() of _profile view. while there is no any related code about _cprofile view in CPass action code!
public function actionCPass()
{
$model = $this->loadModel(Yii::app()->user->id);
$model->scenario = 'CPass';
$this->performAjaxValidation($model);
if(isset($_POST['User'])){
$model->attributes = $_POST['User'];
if($model->validate()){
if($model->verifyPassword($model->currentPass)){
$model->changePassword($model->newPass);
Yii::app()->end('changed');
}
}
}
if(Yii::app()->request->isAjaxRequest)
$this->renderPartial('_cpass',array('model'=>$model));
else
$this->render('update',array('model'=>$model,'form'=>'_cpass'));
}
Output of above code:
<div class="form" >
<form id="change-profile-form" action="index.php?r=upanel/user/cprofile" method="post">
.
.
.
<div class="row">
<input id="update-button" class="submit-button" type="submit" name="yt0" value="update" /> </div>
</form>
</div> <!-- End The Profile Form -->
<div id="change-profile-form_es_" class="errorSummary" style="display:none">resole following errors:
<ul><li>dummy</li></ul></div>
Now understand what is the issue? The problem there is only with Ajax request and when disabled the javascript in the browser the CPass action acts truly.
Excuseme if firstly explained very bad.
Thanks friends
*Edit #2: *
When debugging with Firebug i noticed that snippet of JQuery code didn't change.
When firstly in default action of controller this code:
$this->renderPartial('_cprofile',array('model'=>$model));
be run following JQuery code will create: (As you know following code is related to CHtml::ajaxSubmitButton)
$('body').on('click','#update-button',function(){jQuery.ajax({'type':'POST','data':$('#change-profile-form').serialize(),'success':callback,'beforeSend':before,'url':'/x/index.php?r=upanel/user/CProfile','cache':false});return false;});
So when _cpass view renders with renderpartial() method in CPass action, the above JQuery code must be changed but will not change. I guess it must be the following code:
$('body').on('click','#update-button',function(){jQuery.ajax({'type':'POST','data':$('#change-cpass-form').serialize(),'success':callback,'beforeSend':before,'url':'/x/index.php?r=upanel/user/CPass','cache':false});return false;});
So my problem is with JQuery code generated for CHtml::ajaxSubmitButton. Can anyone help me?
Solved
With applying uniqueId for ajaxSubmitButton and setting CController::processOutput() to True in Controller Action solved.
Summary Code:
actionCPass:
public function actionCPass()
{
$model = $this->loadModel(Yii::app()->user->id);
$model->scenario = 'CPass';
$this->performAjaxValidation($model);
if(isset($_POST['User'])){
$model->attributes = $_POST['User'];
if($model->validate()){
if($model->verifyPassword($model->currentPass)){
$model->changePassword($model->newPass);
Yii::app()->end('changed');
}
}
}
if(Yii::app()->request->isAjaxRequest)
$this->renderPartial('_cpass',array('model'=>$model),false,true);
else
$this->render('update',array('model'=>$model,'form'=>'_cpass'));
}
_cpass.php:
.
.
.
<?php
echo CHtml::ajaxSubmitButton(
'update',
Yii::app()->createUrl('upanel/user/CPass'),
array(
'type'=>'POST',
'data'=>"js:$('#change-pass-form').serialize()",
'success'=>'callback',
'beforeSend'=>'before',
),
array(
'id'=>'update-button'.uniqid(),
'class'=>'submit-button',
)
);
.
.
.
?>
Rename one/both of your button ids. This means the event handlers will be attached to different buttons.
Use renderPartial('view.path',array(parameter_array),false,true); when returning a view via Ajax. The last parameter of CController::renderPartial() calls CController::processOutput() which inserts the required client scripts at appropriate places.
I think I understand your problem, you are wondering why the page does not have the surrounding <div id='profile-container'> and </div>.
I think this may have something to do with the render functions only being able to run once per view called (so it only renders the inside view), you can test this by removing the renderPartial from the update page and see if it prints the blank div.
One way you could get around this is to instead of doing the two renders, always call each page (even in the ajax requests) but pass an extra attribute if it was an ajax request. Then on each of the pages begin and end a custom widget that contains the surrounding template you want on those pages (or just write it in manually).
Example:
controller
public function actionCProfile()
{
// ... same as your example
if(Yii::app()->request->isAjaxRequest){
$this->renderPartial('_cprofile',array('model'=>$model, 'wasAjax'=>false));
} else {
$this->renderPartial('_cprofile',array('model'=>$model, 'wasAjax'=>true));
}
}
then in your view just check if wasAjax is true, if it is then print the surrounding div (or extra elements). If this is big or could change later on, put it in a custom widget.
I'm using Yii framework to create a really simple 1 text-area field and 2 hidden inputs with predefined values sent from the server.
The way it should work is as expected, I mean, you write something on that text-area and you click on the send button. An ajax validation is made (only requisite for the text-area is that is shouldn't be empty) and if validated, save the data and redirect to some other page.
The problem is that it won't save any data if validation error was triggered.
I mean, if I go to the page, write something and hit on the send button, data will be saved and I'll be redirected correctly. But if I go to the page, hit the send button (without typing anything in the text-area), wait for the error to appear (note that this is done via ajax, so no page-reload here), write something and hit send again Yii is going to start making a request after a request in an infinite loop.
I already have checked the data being sent, and everything is fine (both data and action-url).
Here is my Controller code
public function actionView($id)
{
$user = Usuario::model()->findByAttributes(
array(
'nick'=>Yii::app()->user->getId()
)
);
$dataProvider=new CActiveDataProvider('Mensaje', array(
'criteria'=>array(
'with'=>array('usuario', 'usuario.detallesusuario'),
'condition'=>'Tema_idtema='.$id
),
'pagination'=>array(
'pageSize'=>1000,
),
));
$this->render('view',array(
'model'=>$this->loadModel($id),
'usuario_id'=>$user->idusuario,
'tema_id'=>$id,
'dataProvider'=>$dataProvider,
));
}
public function actionCreateMessage(){
$model=new Mensaje;
$this->performAjaxValidation($model);
if(isset($_POST['Mensaje']))
{
$model->attributes=$_POST['Mensaje'];
$model->fecha_hora=new CDbExpression('NOW()');
$model->save();
$this->redirect(array('view', 'id'=>$model->Tema_idtema));
}
}
And the code from the View
<?php
$model = new Mensaje();
echo $this->renderPartial('_mensaje_form', array(
'model'=>$model,
'usuario_id'=>$usuario_id,
'tema_id'=>$tema_id,
),
false, //return instead of echo
true //post-process
);
?>
Here is the "_mensaje_form" code
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'mensaje-form',
'action'=>CHtml::normalizeUrl(array('tema/createMessage')),
'enableAjaxValidation'=>true,
'clientOptions'=>array(
'validateOnSubmit'=>true,
'validateOnChange'=>false,
'validateOnType'=>false,
),
)); ?>
<?php echo $form->errorSummary($model); ?>
<div class="row" style="margin:20px 5px 0 176px;">
<?php echo $form->labelEx($model,'mensaje'); ?>
<?php echo $form->textArea($model,'mensaje',array('rows'=>6, 'cols'=>50)); ?>
<?php echo $form->error($model,'mensaje'); ?>
<?php echo $form->hiddenField($model, 'Tema_idtema', array('value'=>$tema_id)); ?>
<?php echo $form->hiddenField($model, 'Usuario_idusuario', array('value'=>$usuario_id)); ?>
</div>
<div class="row buttons" style="margin:-3px 0 -8px 176px;">
<?php echo CHtml::submitButton($model->isNewRecord ? 'Responder' : 'Guardar'); ?>
</div>
<?php $this->endWidget(); ?>
Any idea why I'm getting that loop?
This might help you,
http://www.yiiframework.com/forum/index.php/topic/10427-ajax-clientscript/
in your view, the last parameter "true" in renderPartial may be the problem.
My guess (a bit long shot) that form id in your preformAjaxValidation() might be wrong, so it causes the loop! since it won't get in the body of the if and hence executes Yii::app()->end(); !!
Check it in your controller:
protected function performAjaxValidation($model)
{
if(isset($_POST['ajax']) && $_POST['ajax']==='exact-form-id')//should be mensaje-form
{
echo CActiveForm::validate($model);
Yii::app()->end();
}
}