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

  1. Problem
  2. When is it needed?
  3. The solution

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 a required field while fax is not. Yet, if submitted, both should be validated as 'phone numbers', hence use a custom validator class, PcSimplePhoneValidator).
  • So, your 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, it's 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.

5 1
6 followers
Viewed: 26 048 times
Version: 1.1
Category: How-tos
Written by: Boaz
Last updated by: mrun
Created on: Sep 11, 2012
Last updated: 8 years ago
Update Article

Revisions

View all history

Related Articles