Yii 1.1: How to "masquerade" a non-required form element as 'required' one (in the view only)

5 followers

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. 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).
  • So, you're rules() method will need to look like this:
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 echo $form->labelEx($model, 'phone'); ?>
<?php echo $form->textField($model, 'phone', array('size' => 30, 'maxlength' => 30)); ?>
<?php echo $form->error($model, 'phone'); ?>

to:

<?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.

Total 2 comments

#9810 report it
Boaz at 2012/09/12 01:56am
@marcovtwout

I think that you're right. I just learned a new thing. Still, masquerading a form label as a required one can be useful in other occasions. Thanks for the input!

#9807 report it
marcovtwout at 2012/09/11 06:04pm
Better solution

If I onderstand your problem correctly, this seems to me like a hacky solution. Use skipOnError instead if you just want to prevent double message. http://www.yiiframework.com/doc/api/1.1/CValidator#skipOnError-detail

Leave a comment

Please to leave your comment.

Write new article