I have a field customercode. it will be disabled if the value of the listbox is staff and enabled if the listbox value is admin. If case of admin, the customercode is required.
I can think of two ways, or a combination of those. Both need some tweaking for perfect results, but they are pretty good:
1) Scenario: Note that I have two fields / attributes: text / dropdown In your controller:
public function actionScenario()
{
$model=new ScenarioForm;
// if it is ajax validation request
if(isset($_POST['ajax']) && $_POST['ajax']==='scenario-form')
{
if($_POST['ScenarioForm']['dropdown'] == 'admin')
$model->scenario = 'admin';
echo CActiveForm::validate($model);
Yii::app()->end();
}
// collect user input data
if(isset($_POST['ScenarioForm']))
{
$model->attributes=$_POST['ScenarioForm'];
if($model->dropdown == 'admin')
$model->scenario = 'admin';
// validate user input
$model->validate();
//do other stuff
}
// display the login form
$this->render('scenario', array('model'=>$model));
}
As you can see, I check if the dropdown value is admin; if so I change the scenario of the model to 'admin'. In the model rules, I have this:
public function rules()
{
return array(
array('dropdown', 'required'),
array('text', 'required', 'on' => 'admin'),
);
}
You see, text is only required when the scenario is admin. When you now have admin in the dropdown, and nothing in your text field, and submit the form, you will get the right errors. If you want instant, ajax feedback, when the user changes the dropdown, you might want this in your view:
<?php echo $form->labelEx($model,'dropdown'); ?>
<?php echo $form->dropDownList($model,'dropdown', array('admin' => 'Admin', 'staff' => 'Staff!')); ?>
<?php echo $form->error($model,'dropdown', array('afterValidateAttribute' => 'js:function(form, attribute, data, hasError)
{
mSettings = $.fn.yiiactiveform.getSettings(form);
$.fn.yiiactiveform.updateInput(mSettings.attributes[1], data, form)
}')); ?>
The third parameter in the error for dropdown is an array which contains several html options, such asthe callback that is called after the dropdown is validated with ajax. Normally, only the current field is updated when you do ajax-validation (even though you get all errors). So we specify in the callback that also the errors for the text field should be updated. You will see now that you get an error when you select admin in the dropdown (not on startup).
It's not perfect, since you don't get your nice required * for the text field, and you get the warning immediately. I am not sure if Yiiactiveform has a function for drawing the field decoration, rather then the warning. But you could probably extend it to do that, or use custom js in the callback. If you just need normal validation after submit, you can also add the required class to the text label with custom Javascript. I am not sure at the moment if CActiveForm has a special parameter in the attribute for that.
2) custom validation rule. Similar to one, although you don't use a scenario (but still the js callback in the view). Instead, you create a custom validation rule for the dropdown, and put it into the rules array. When the dropdown changes, we add an error to the text field.
public function check_dropdown($attribute,$params){
if($this->$attribute=="admin"){
$this->addError('text', 'Please enter Text!');
$this->clearErrors('text');
}
}
public function check_text($attribute,$params){
if($this->$attribute!=""){
$this->clearErrors('text');
}
}
Here you don't need the to set the scenario in the controller. But you lose the required rule. Same issue here also with the missing asterisk.
I would probably go with way 1. If you don't want an outright warning, you probably have to read out the error message from the JSON, check if it is the right one, and apply the right class to the label of text with custom Javascript in the callback function.