Yii ajax validation for blog demo - posts/contact form - ajax

In the Yii blog demo, included in the framework download and here:
http://www.yiiframework.com/demos/blog/
ajax validation for form inputs work for the post comment and login forms...
demos\blog\protected\views\comment_form.php
and
demos\blog\protected\views\login.php
both include things like
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'comment-form',
'enableAjaxValidation'=>true,
)); ?>
or
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'login-form',
'enableAjaxValidation'=>true,
)); ?>
I tried adding similar things to views/site/contact.php and views/post/_form.php ('id'=>'contact-form', and 'post-form') but it isn't working (tabbing out of form fields doesn't result in red or green fields depending on if the input is valid or invalid and there are no ajax generated invalid messages either)

Ajax validation consists of 3 phases:
Send an ajax request to server with form fields' values to validate them.
Validate fields and return validation message from server.
Update form fields with the validation messages.
When you set enableAjaxValidation to true, you are taking care of the phase 1 & 3, so there is still phase 2 left.
Phase 2.
By default ajax validation triggers POST ajax calls, with an additional1 'ajax' post parameter, whose value is set to the id of the form being validated. In your case it should be something like: ajax --> contact-form, and ajax --> post-form.
So what you have to do is catch this POST request in your server-side, and send a response after validating the fields which were sent in the request.
The POST request is sent to the form's action url (by default), which in your case will be something like: http://foo/index.php/site/contact, which means you have to change your controllers/SiteController.php's actionContact function:
public function actionContact(){
$model = new ContactForm;
// checking if it is ajax validation request below
if(isset($_POST['ajax']) && $_POST['ajax']==='contact-form') {
echo CActiveForm::validate($model); // validate the form fields sent in POST, and return response
Yii::app()->end(); // end the application
}
// ... leave the rest of the code as is ...
}
In the blog demo's views/site/contact.php there are no error fields so you will not be able to see the messages just yet. To see them add the error fields to the form:
<div class="row">
<?php echo $form->labelEx($model,'name'); ?>
<?php echo $form->textField($model,'name'); ?>
<?php echo $form->error($model,'name'); // this line needs to be added ?>
</div>
Add the error fields similarly for the other inputs.
For the post/_form.php make similar adjustments (from 1st code snippet) to the controllers/PostController.php's actionCreate and actionUpdate methods. Just that your if check will change to:
if(isset($_POST['ajax']) && $_POST['ajax']==='post-form')
Extra Info.
The ajax POST parameter is called the ajaxVar, and it defaults to ajax. You can change a lot of these defaults, like the validation url (action or validationUrl of clientOptions), or the ajaxVar ($_POST['ajax']) of clientOptions. Read the documentation to see the options.
1 In addition to the form's fields.

Related

client side validation not working for model window / ajax-loaded-form in yii

I am using Yii-user extension in the main layout i have a sign up link which is common to all the Cmenu
view/main layout
echo CHtml::link('Signup','#',array('id'=>'regi'));
$("#regi").click(function(){
$.ajax({
type:'GET',
url:'<?php echo Yii::app()->request->baseUrl;?>/index.php/user/registration',
success:function(res){
$("#dispdata").show();
$("#dispdata").html(res);
}
});
});
<div id="dispdata"><div>
**yii user extension **renders this perfectly and even submit its correctly if form values a re valid.
but if the values are incorrect and blank it redirect to url .../user/registration
which is not what my need .I need guidance what do i do such that if the values are incorrect or blank it should not redirect and display the errors in model window.
I did tried but hardly could get the satisfied results
if i place the following the model window itself doesnt appear what do i do
module registrationController i placed
....//some code here (**in yiiuser register controller**)
if ($model->save()) {
echo CJSON::encode(array(
'status'=>'success',
));
}
....//some code here...
Yii::app()->clientScript->scriptMap['jquery.js'] = false;
$this->renderPartial('registration',array('model'=>$model,),false,true);
in module view registration
<?php echo CHtml::ajaxSubmitButton(Yii::t('registration'),CHtml::normalizeUrl(array('user/registration','render'=>false)),array('dataType'=>'json',
'success'=>'function(data) {
if(data != null && data.status == "success") {
$("#registration-form").append(data.data);
}
}')); ?>
can anyone please guide me am working past 10 ten days tried every hook or crook method but could not obtain the results......how can the model window with client side validation be done appear..... Please guide me or let me know something better can be done
rules in registration model
if (!(isset($_POST['ajax']) && $_POST['ajax']==='registration-form')) {
array_push($rules,array('verifyCode', 'captcha', 'allowEmpty'=>!UserModule::doCaptcha('registration')));
as well was not with attributes for reqired field
have changed to
array_push($rules,array('verifyCode', 'captcha','message' => UserModule::t("captcha cannot be blank.")));
and added the verifycode to required field
yet not working,
The simple way is using render method in your Ajax action and creating empty layout for this action. If you do so, validation scripts will be included in the server response. Also you need to exclude jquery.js and other script with Yii::app()->clientScript->scriptMap and include them in main layout always.

Clear validation error message when the value is updated or selected

I have form in yii that validates the form field. When I submit the form it shows the errors.
But when the value of the field with the validation error is updated, the error still present.
I want the message to clear. How should i clear the validation error?
Below the form widget code
<?php $form = $this->beginWidget('CActiveForm', array(
'id'=>'user-form',
'enableAjaxValidation'=>true
)); ?>
In my form I echo the validation error like the code below:
<?php echo $form->error($model, 'firstname'); ?>
I tried the solution from this problem
Trigger Yii field validation onchange of another field
$('#user-form').change(function(){
var settings = $(this).data('settings');
$.each(settings.attributes, function () {
this.status = 2; // force ajax validation
});
$(this).data('settings', settings);
// trigger ajax validation
$.fn.yiiactiveform.validate($(this), function (data) {
$.each(settings.attributes, function () {
$.fn.yiiactiveform.updateInput(this, data, $(this));
});
});
});
But the error message is still not cleared. I have confirmed that the ajax request is sent and there are response as its showed on the firebug console.
[EDIT]
It seems those validation errors for "select" fields are the ones that are not updated/cleared only.
[EDIT]
All the validation errors that are printed/echo after the form is submmitted will not disappear even if the value is supplied or change to satisfy the validation rules.
Place this just above the // trigger ajax validation comment:
$('.errorSummary, .errorMessage').hide();
This should reset the errors before they get re-validated.
In my case I added the code below on the page to remove the red highlight on input field on the form.
$('#user-form select, #user-form input').change(function(){
field = $(this).attr('id');
if($('#'+field+'_em').text() == ''){
$(this).removeClass('error');
}
});
I also add the updateInput function on framework/web/js/source/jquery.yiiactiveform.js so it will remove the validation error for certain field.
if(hasError == false){
$error.toggle(hasError);
$el2 = form.find('#' + attribute.id);
$el2.removeClass(attribute.errorCssClass);
}
I am not sure if this the proper solution but it works for me.
With your form widget code, i don't think ajax validation won't work.
To enable Ajax validation on form you should configure your widget as below,
<?php
$form = $this->beginWidget('CActiveForm', array(
'id'=>'user-form',
'enableAjaxValidation' => true,
'clientOptions' => array(
'validateOnSubmit' => true,
),
));
?>
With this configuration, your form will be validated when form field lost the focus(blur).
Try it, It will give the solution for your problem.

Yii ClientSide Validation on Render Partial not Working

I have a Yii form which calls a render partial from another model (team has_many team_members). I want to call via ajax a partial view to add members in team/_form. All works (call, show, save) except for ajax validations (server and client side). If i submit form, member's model isn't validating, even in client side, it's not validating the required fields.
Any clue?
//_form
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'team-form',
'enableAjaxValidation'=>true,
'enableClientValidation'=>true,
'clientOptions'=>array(
'validateOnSubmit'=>true,
'validateOnChange'=>true
),
'htmlOptions' => array('enctype' => 'multipart/form-data'),
)); ?>
//Controller
public function actionMember($index)
{
$model = new TeamMember();
$this->renderPartial('_member',array(
'model'=> $model, 'index'=> $index
)
,false,true
);
}
public function actionCreate()
{
$model=new Team;
$members = array();
if(isset($_POST['Team']))
{
$model->attributes=$_POST['Team'];
if(!empty($_POST['TeamMember'])){
foreach($_POST['TeamMember'] as $team_member)
{
$mem = new TeamMember();
$mem->setAttribute($team_member);
if($mem->validate(array('name'))) $members[]=$mem;
}
}
$this->redirect(array('team/create','id'=>$model->id,'#'=>'submit-message'));
}
$members[]=new TeamMember;
$this->performAjaxMemberValidation($members);
$this->render('create',array(
'model'=>$model,'members'=>$members
));
}
//_member
<div class="row-member<?php echo $index; ?>">
<h3>Member <?php echo $index+1; ?></h3>
<div class="row">
<?php echo CHtml::activeLabel($model, "[$index]name",array('class'=>'member')); ?>
<?php echo CHtml::activeTextField($model, "[$index]name",array('class'=>'member')); ?>
<?php echo CHtml::error($model, "[$index]name");?>
</div>
</div>
ProcessOutput was set to true. No dice.
Switch renderPartial() to render(). No dice.
If you will look at the CActiveForm::run:
$cs->registerCoreScript('yiiactiveform');
//...
$cs->registerScript(__CLASS__.'#'.$id,"jQuery('#$id').yiiactiveform($options);");
Then you will understand that you validation will not work, because you render partial and not the whole page. And these scripts show up at the bottom of the page. So you should solve this by execute these scripts.
After you partial is rendered, try to get activeform script which should be stored at the scipts array:
$this->renderPartial('_member',array('model'=> $model, 'index'=> $index));
$script = Yii::app()->clientScript->scripts[CClientScript::POS_READY]['CActiveForm#team-form'];
after, send it with rendered html to page:
echo "<script type='text/javascript'>$script</script>"
Also remember before you will append recieved html on the page you should include jquery.yiiactiveform.js, if you not already did it(by render another form, or registerCoreScript('yiiactiveform')), on the page from calling ajax request. Otherwise javascript error will raised.
Hope this will help.
Edit:
Sorry I'm not understood that you are render part of form and not the whole. But you validation will not work exactly with the same issue. Because jQuery('#$id').yiiactiveform($options); script was not created for the field.
The actual problem is that the ActiveForm saves its attributes to be validated in the "settings" data attribute. I see you are already using indexes so what you need to add the new elements to this settings object in order for the validation to work. After the ajax response this is what must be done:
//Get the settings object from the form
var settings = $("#form").data('settings');
//Get all the newly inserted elements via jquery
$("[name^='YourModel']", data).each(function(k, v) {
//base attribute skeleton
var base = {
model : 'YourModel',
enableAjaxValidation : true,
errorCssClass : 'error',
status : 1,
hideErrorMessage : false,
};
var newRow = $.extend({
id : $(v).attr('id'),
inputID : $(v).attr('id'),
errorID : $(v).attr('id') + '_em_',
name : $(v).attr('name'),
}, base);
//push it to the settings.attribute object
settings.attributes.push(newRow);
});
//update the form
$("#form").data('settings', settings);
```
This way the ActiveForm will be aware of the new fields and will validate them.
Well, setting processOutput to true in renderPartial (in order to make client validation works on newly added fields) will not help in this case since it will only work for CActiveForm form and you don't have any form in your _member view (only input fields).
A simple way to deal with this kind of problem could be to use only ajax validation, and use CActiveForm::validateTabular() in your controller to validate your team members.

Yii Displaying Image dynamically dependent on dropdown

I'm trying to display an image but is dependent on a dropdown list in Yii. I can get the image from the database and display it, but how to do it dynamically depending on the choice from the dropdown?
Here is the reference: http://www.yiiframework.com/wiki/24/creating-a-dependent-dropdown#hh0 but, let me show you how to do it.
First all all, we need a div where the image will be displayed; I'll create one whose id will be 'img'. Then, the ajax request is specified inside the dropdownlist() as follows:
<?php echo $form->labelEx($model,'attribue'); ?>
<?php echo $form->dropDownList($model,'attribute',
array(/*The options in the DropDownList*/),
array(
'ajax'=>array(
'type'=>'POST',
'url'=>CController::createUrl('YourController/actionWhichEchoesTheImage'),
'update'=>'#img',
)));
?>
<div id="img"> // <---- the result of the ajax call will be displayed here
</div>
In the 'url' attribute we specify the function which will be called when the ajax request triggers. In the 'update' attribute we specified the div where will be displayed the result of calling that function (the image).
Finally, we have to declare the action actionWhichEchoesTheImage(). Let's declare it in the current controller. It would look something like this:
public function actionWhichEchoesTheImage()
{
if(isset($_POST['ModelName']['attribute']))
/*Here goes your code to load the image*/
echo CHtml::image(//Check the reference to see how to set this function);
}
Check CHtml::image() here: http://www.yiiframework.com/doc/api/1.1/CHtml/#image-detail

Codeigniter Form Validation: How to redirect to the previous page if found any validation error?

I am using Codeigniter's validation class to validate my form. Could you please tell me how to redirect to the previous page from controller if found any validation error?
In my controller:
if ($this->form_validation->run() == FALSE){
//**** Here is where I need to redirect
} else {
// code to send data to model...
}
I extended the URL helper for this.
https://github.com/jonathanazulay/CodeIgniter-extensions/blob/master/MY_url_helper.php
In your controller:
$this->load->helper('url');
redirect_back();
Just put the MY_url_helper.php in application/helpers and you're good to go.
UPDATE
You want to post a form, validate it, then show the form again with the validation errors if validation fails, or show something entirely different if validation passes.
The best way to do this is to post a form back to itself. So the action of your form would be action="". This way, in your method, you can check to see if the form was submitted, and determine what to do there:
// in my form method
if ($this->input->post('submit')) // make sure your submit button has a value of submit
{
// the form was submitted, so validate it
if ($this->form_validation->run() == FALSE)
{
$this->load->view('myform');
}
else
{
$this->load->view('formsuccess');
}
}
else
{
// the form wasn't submitted, so we need to see the form
$this->load->view('myform');
}
OLD ANSWER
You can always pass the current URI in a hidden field in the form:
<input name="redirect" type="hidden" value="<?= $this->uri->uri_string() ?>" />
And then redirect if the validation fails:
redirect($this->input->post('redirect'));
Or you can set the redirect url in a flashdata session variable:
// in the method that displays the form
$this->session->set_flashdata('redirect', $this->uri->uri_string());
And then redirect if the validation fails:
redirect($this->session->flashdata('redirect'));
Well, usually you should do like this (pseudocode for now):
if form_validation == false --> the form is either not submitted yet or validation failed --> load the form view;
if form_validation == true --> do the processing.
This means you have to stay within the same controller. Your code should already be doing this behaviour, which is the intended one.
If you still feel the urge to redirect, call the appropriate function:
redirect('updatebatch/get/40','refresh');
// assuming 'updatebatch' is the name of your controller, and 'sundial' just a folder
I have created a function inside a library to create redirects when I need them.
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
class Functions {
public function generateRedirectURL()
{
$CI =& get_instance();
$preURL = parse_url($_SERVER['REQUEST_URI']);
$redirectUrl = array('redirectUrl' => 'http://' . $_SERVER['SERVER_NAME'] . $preURL['path']);
$CI->session->set_userdata($redirectUrl);
}
}
//End of the file
and when you want to create the redirect to that page, just write on the function:
$this->load->library('functions'); //you can put it in the autoloader config
$this->functions->generateRedirectURL();
Then you only need to call:
redirect($this->session->userdata['redirectUrl']);

Resources