Difference between #2 and #3 of How to "masquerade" a non-required form element as 'required' one (in the view only)

unchanged
Title
How to "masquerade" a non-required form element as 'required' one (in the view only)
unchanged
Category
How-tos
unchanged
Tags
required field, validation rules
changed
Content
Problem
------------------
In a nutshell, the task at hand is to mark (or render) a model attribute in the
typical "_form.php" view file with the 'required' red asterisk while
this attribute is not marked as required in the model's rule()
method.required. 
If you're interested only in the solution, jump ahead to the 'solution' section
below.

When is it needed?
----------------------

Consider the following use case:

- You have a model with two phone numbers attributes: _phone_ and _fax_. Phone
is q required field while fax is not. Yet, if submitted, both should be
validated as 'phone numbers', hence use a custom validator class,
[PcSimplePhoneValidator](http://www.yiiframework.com/extension/pcsimplephonevalidator/)).
- So, you're rules() method will need to look like this:

~~~
[php]
public function rules() {
	return array(
		array('phone', 'required'),
		array('phone', 'PcSimplePhoneValidator'),
		array('fax', 'PcSimplePhoneValidator', 'allowEmpty' => true),
	//...
	);
}
~~~

- Now, with the above rules if the form is submitted with empty phone number,
you'll get two error messages about empty phones - one from CRequiredValidator
and one from 
PcSimplePhoneValidator that is configured to disallow empty phone numbers (only
empty fax is allowed).
- So, you take off the 'required' line in the rules() method above. The line
after it will take care that phone is always submitted, and when submitted its
validated with our needed validator. 
- But, once 'phone' is no more a 'required' attribute in the rules() method, its
no longer rendered as a required field, taking off the usual red asterisk that
followed the label. 

The solution
--------
We'll change the label rendering method. Change the phone number rendering in
_form.php from:

~~~
[php]
<?php echo $form->labelEx($model, 'phone'); ?>
<?php echo $form->textField($model, 'phone', array('size' => 30,
'maxlength' => 30)); ?>
<?php echo $form->error($model, 'phone'); ?>
~~~

to:

~~~
[php]
<?php echo CHtml::activeLabel($model, 'phone', array('required' => true));
?>
<?php echo $form->textField($model, 'phone', array('size' => 30,
'maxlength' => 30)); ?>
<?php echo $form->error($model, 'phone'); ?>
~~~

As you can see, the only change is the switch from _$form->labelEx()_ to
_CHtml::activeLabel()_.

That will render the phone label as 'required' in the same way, with the same
CSS class as the rest of our 'required' fields in the form.
Write new article