Help test the new widget CActiveForm

Qiang, please, check my code again (if you didn’t understood my concept - activeElement is virtual property of DOMElement), but if you didn’t like it… try to verify something like:


// in initialization

$form.find(':submit').bind('mouseup keyup',function(){

    $form.data('activeElement',this);

});




// for correct submit

($form.data('activeElement')||$form.find(':submit:first')).click();



Sorry for misunderstanding (I thought you were talking about activeElement that is only available in IE).

I have verified your solution and applied it in SVN. Thanks!

Thanks!

  • 2 enhancements:



if(button) // this works forever (even if button not presents)


// try to use:

if(button.length) // or if(button.is(':submit'))



+in this case change:


$form.data('submitObject',$(this)); // instead of $form.data('submitObject',this);

Thanks! Fixed.

Hello maybe someone could help .

AJAX Validation is not working when i used CActiveForm.

there is no JavaScript loaded at all. so what i do wrong

i used this




<?php $form=$this->beginWidget('CActiveForm',array('enableAjaxValidation'=>true)); ?>



but there is no JavaScript loaded why ???

do i need a ajaxsubmitButton ?

i used the Yii SVN version.

how could one use CActiveForm to fill/validate several models within one form?

there is a tutorial for the normal CHtmlform within the Cookbook but i am not able apply it to the cactiveform wrapper.

not possible or havent i found the right switch^^

The first parameter CActiveForm::validate() can be an array of models.

Maybe CActiveForm::_attributes are empty? There is following line in run() method:




if(!$this->enableAjaxValidation || empty($this->_attributes)) return;



You have to write in your view "$from->error…", like this: (see second line)




<?php echo $form->labelEx($model, 'Name'); ?>

<?php echo $form->error($model,'Name'); ?>

<?php echo $form->textField($model, 'Name'); ?>



I have the same problem. It isn’t submitting as AJAX, even after removing and re-creating the assets directory. This is my view:




<div class="form">';

$form = $this->beginWidget( "CActiveForm", 

			array(

				'enableAjaxValidation' => true,

				'validateOnType'       => true,

				'id'                   => "hv_create_listing_form",

				'action'               => "/listing/save",

				'clientOptions'	       => array( 'validateonsubmit' => true ),

			) 

		);

echo '

	<input type="hidden" name="member_id" value="'.$member_id.'"/>

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

	'.$form->errorSummary( $model ).'

	<div class="row">

		'.$form->labelEx($model,'crop_type_id').'

 		'.$form->dropDownList($model,'crop_type_id',CHtml::listData( $crop_types, 'id', 'name' ), 

									   array('prompt'=>'Select...')).'

	</div>

	<div class="row">

		'.$form->labelEx( $model, 'variety' ).'

		'.$form->textField( $model,'variety',array('size'=>40, 'maxlength'=>80)).'

		'.$form->error( $model, 'variety' ).'

	</div>

	<div class="row">

		'.$form->labelEx($model,'description').'

		'.$form->textArea($model,'description',array('rows'=>2, 'cols'=>45)).'

		'.$form->error( $model, 'description' ).'

	</div>';


if ( strlen($member_id) == 0 ) {

  echo '

	<div class="row">

		'.$form->labelEx($model,'poster_id').'

		'.$form->dropDownList($model,'poster_id',CHtml::listData( Member::model()->findAll(), 'id', 'full_name' ), array('prompt'=>'Select...')).'

	</div>';

 }

if ( strlen($type_id) == 0 ) {

  echo '

  	<div class="row">

		'.$form->labelEx($model,'post_type_id').'

		'.$form->dropDownList($model,'post_type_id',CHtml::listData( PostingType::model()->findAll(), 'id', 'name' ), array('prompt'=>'Select...')).'

	</div>';

 }

echo '

	<div class="row">

		'.$form->labelEx( $model, 'quantity' ).'

		'.$form->textField( $model, 'quantity', array('size'=>10, 'maxlength'=>10)).'

		'.$form->error( $model, 'quantity' ).'

		'.$form->dropDownList( $model, 'qty_type_id', CHtml::listData( QuantityType::model()->findAll(), 'id', 'name' ), array('prompt'=>'Select...')).'

	</div>

	<div class="row">

		'.$form->labelEx( $model, 'price' ).'

		'.$form->textField( $model, 'price', array('size'=>10, 'maxlength'=>10) ).'

		'.$form->error( $model, 'price' ).'

	</div>

	<div class="row buttons">

		'.CHtml::submitButton( $model->isNewRecord ? 'Create' : 'Save' ); 

	</div>

';

$this->endWidget();

echo '

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

';




I am also not having any luck with this making the ajax request.

From a clean install of 1.1.1 I made the modifications and tried several things, but the form always does the regular post:

My controller code:




	public function actionContact()

	{

		$model=new ContactForm;

		$this->performAjaxValidation($model);


		if(isset($_POST['ContactForm']))

		{

			$model->attributes=$_POST['ContactForm'];

			if($model->validate())

			{

				$headers="From: {$model->email}\r\nReply-To: {$model->email}";

				mail(Yii::app()->params['adminEmail'],$model->subject,$model->body,$headers);

				Yii::app()->user->setFlash('contact','Thank you for contacting us. We will respond to you as soon as possible.');

				$this->refresh();

			}

		}

		$this->render('contact',array('model'=>$model));

	}

	

	protected function performAjaxValidation($model)

	{

//		print_r($_POST);

//		die();

	    if(isset($_POST['ajax']) && $_POST['ajax']==='yw0')

	    {

	        echo CActiveForm::validate($model);

	        Yii::app()->end();

	    }

	}



My view




<?php

$this->pageTitle=Yii::app()->name . ' - Contact Us';

$this->breadcrumbs=array(

	'Contact',

);

?>


<h1>Contact Us</h1>


<?php if(Yii::app()->user->hasFlash('contact')): ?>


<div class="flash-success">

	<?php echo Yii::app()->user->getFlash('contact'); ?>

</div>


<?php else: ?>


<p>

If you have business inquiries or other questions, please fill out the following form to contact us. Thank you.

</p>


<div class="form">


<?php $form=$this->beginWidget('CActiveForm', array(

	'enableAjaxValidation'=>true,


	//'clientOptions'        => array( 'validateonsubmit' => true ),


)); ?>


	<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,'name'); ?>

		<?php echo $form->textField($model,'name'); ?>

		<?php echo $form->error($model,'name'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($model,'email'); ?>

		<?php echo $form->textField($model,'email'); ?>

		<?php echo $form->error($model,'email'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($model,'subject'); ?>

		<?php echo $form->textField($model,'subject',array('size'=>60,'maxlength'=>128)); ?>

		<?php echo $form->error($model,'subject'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($model,'body'); ?>

		<?php echo $form->textArea($model,'body',array('rows'=>6, 'cols'=>50)); ?>

		<?php echo $form->error($model,'body'); ?>

	</div>


	<?php if(extension_loaded('gd')): ?>

	<div class="row">

		<?php echo $form->labelEx($model,'verifyCode'); ?>

		<div>

		<?php $this->widget('CCaptcha'); ?>

		<?php echo $form->textField($model,'verifyCode'); ?>

		</div>

		<div class="hint">Please enter the letters as they are shown in the image above.

		<br/>Letters are not case-sensitive.</div>

	</div>

	<?php endif; ?>


	<div class="row submit">

		<?php echo CHtml::submitButton('Submit'); ?>

	</div>


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


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


<?php endif; ?>



try this .


<?php echo CHtml::submitButton('ClickMe',

				array(

				'ajax' => array(

				'type'=>'POST', //request type

				'url'=>"index.php?r=site/loginAjax", //url to call

				'update'=>'#form', 

				))


				); ?>

this post is kind of old, but I would like to mention two problems I have had with the CActiveForm class:

  1. The CActiveForm::validate() function does not handle Tabular input like echo $form->textField($item,"[$i]name");, as described here: http://www.yiiframework.com/doc/guide/form.table. It seems that it is not aware of the [$i] trick when it builds the model to validate from the $_POSt variable.

  2. The “validateOn” “clientOptions” are a little confusing - namely that in order for ‘validateOnSubmit’=>true to work I had to set ‘validateOnChange’=>false. OnChange must be set by default somewhere?

Works pretty well otherwise!

I think there is a problem with ajax validation when I’m using ‘checkBoxList’ in ‘CActiveForm’.




<?php echo $form->checkBoxList($model,'diag',CHtml::listData($diag,'id','name')); ?>



generates:




...

<input type="hidden" name="Transaction[diag]" value="" id="ytTransaction_diag"/>

<input type="checkbox" name="Transaction[diag][]" value="5" id="Transaction_diag_0" class="jqParentHl"/> 

<label for="Transaction_diag_0">Andrzej Gradek</label><br />

...



As we can see hidden field id is [color="#FF0000"]"ytTransaction_diag"[/color] and other fields id is [color="#FF0000"]"Transaction_diag_x"[/color]

while function $.fn.yiiactiveform.getInputContainer in jquery.yiiactiveform.js is looking for element called Transaction_diag not [color="#FF0000"]ytTransaction_diag[/color] to obtain proper input container.




	$.fn.yiiactiveform.getInputContainer = function(attribute) {

		if(attribute.inputContainer == undefined)

			return $('#'+attribute.inputID).closest('div');

		else

			return $(attribute.inputContainer).filter(':has("#'+attribute.inputID+'")');

	};



So in this case $.fn.yiiactiveform.updateInput in jquery.yiiactiveform.js is not adding properly ‘errorCssClass’ or ‘successCssClass’.

Same thing when I’m using ‘radioButtonList’.

Can someone correct me if I’m wrong?..

Hi, sorry to drag out this old thread, but I think there’s a problem with the CRadioButtonList clientside validation. It doesn’t correctly perform the validation.

This is my model code fragment:




...

public function rules()

{

	// NOTE: you should only define rules for those attributes that

	// will receive user inputs.

		return array(

			array('field_name, field_slug, field_type', 'required'),

			array('field_slug', 'unique'),

			array('field_option_group_id, form_id, visible, required, is_child', 'numerical', 'integerOnly'=>true),

			array('validation', 'length', 'max'=>45),

			array('field_name, field_slug', 'length', 'max'=>150),

			// The following rule is used by search().

			// Please remove those attributes that should not be searched.

			array('field_id, field_name, field_type, field_option_group_id, field_slug, visible, required, validation, is_child', 'safe', 'on'=>'search'),

		);

	}

}

...



My view code fragment:




...

$form=$this->beginWidget('CActiveForm', array(

	'id'=>'form-field-form',

	'enableAjaxValidation'=>false,

	'enableClientValidation'=>true,

	'clientOptions'=>array(

		'validateOnSubmit'=>true,

	)

)); 

...

	<div class="row">

		<?php echo $form->labelEx($model,'field_type'); ?>

		<?php echo $form->radioButtonList($model,'field_type', $model->getFormFieldTypes()); ?>

		<?php echo $form->error($model,'field_type'); ?>

	</div>

...

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

...



The generated HTML fragment:




...

<form id="form-field-form" action="/ccnsw/admin/formField/create" method="post">

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

	

	<div class="row">

		<label for="FormField_field_name" class="required">Field Name <span class="required">*</span></label>

		<input size="60" maxlength="150" onkeyup="js:genslug($(this));" name="FormField[field_name]" id="FormField_field_name" type="text" />

	</div>


	<div class="row">

		<label for="FormField_field_slug" class="required">Field Slug <span class="required">*</span></label>

		<input size="60" maxlength="150" class="FormField" name="FormField[field_slug]" id="FormField_field_slug" type="text" />

	</div>


	<div class="row">

		<label for="FormField_field_type" class="required">Field Type <span class="required">*</span></label>

   	<!-- // SEE ID below -->

        <input id="ytFormField_field_type" type="hidden" value="" name="FormField[field_type]" />

		

		<input id="FormField_field_type_0" value="text" type="radio" name="FormField[field_type]" /> 

		<label for="FormField_field_type_0">Text field</label><br/>

		<input id="FormField_field_type_1" value="checkbox" type="radio" name="FormField[field_type]" /> 

		<label for="FormField_field_type_1">Checkbox</label><br/>

		<input id="FormField_field_type_2" value="date" type="radio" name="FormField[field_type]" /> 

		<label for="FormField_field_type_2">Date entry</label><br/>

		<input id="FormField_field_type_3" value="timestamp" type="radio" name="FormField[field_type]" /> 

		<label for="FormField_field_type_3">Timestamp</label><br/>


		<input id="FormField_field_type_4" value="currency" type="radio" name="FormField[field_type]" /> 

		<label for="FormField_field_type_4">Currency</label><br/>

		<input id="FormField_field_type_5" value="list" type="radio" name="FormField[field_type]" /> 

		<label for="FormField_field_type_5">Dropdown list</label><br/>

		<input id="FormField_field_type_6" value="multi_check" type="radio" name="FormField[field_type]" /> 

		<label for="FormField_field_type_6">Checkbox list</label><br/>

	</div>

	...

</form>



The generated validation JS:




...

{'id':'FormField_field_type', //<< SEE ID

'inputID':'FormField_field_type',

'errorID':'FormField_field_type_em_',

'model':'FormField','name':'FormField[field_type]',

'enableAjaxValidation':false,

'clientValidation':function(value, messages, attribute) {


if($.trim(value)=='') {

	messages.push("Field Type cannot be blank.");

}




if($.trim(value)!='') {

	

if(value.length>45) {

	messages.push("Field Type is too long (maximum is 45 characters).");

}


}


}},

...



When I submit the form with out selecting a radio button, the validation triggers and I see the message saying ‘Field Type cannot be blank’. However, if I select a radio button and re-submit, I still get the same error, when it should validate with out error.

I think it may be due to the ID not matching up between the generated HTML and JS (see where I’ve added ‘SEE ID’ comment in HTML and JS fragments above). I’m not cluey as to how the clientside validation code is meant to work, but shouldn’t it be using the ‘name’ property to check if a value is set for this group?

Let me know if something doesn’t make sense or need me to elaborate on any of it further.

Thanks! :)