Extending CActiveForm for some form display fixes and language tweaks

In this simple example I'll demonstrate how to extend CActiveForm class to overload some drawing functions to achieve some commonly used fixes in forms.

The colon

Here is overloaded version of CActiveForm.labelEx that adds colon (:) at the end of text of label with respecting CHtml::$afterRequiredLabel and CHtml::$beforeRequiredLabel

class MyActiveForm extends CActiveForm
{
	public function labelEx2($model, $attribute, $htmlOptions = array())
	{
		if ($model->isAttributeRequired($attribute))
                {
                        $arl = CHtml::$afterRequiredLabel;
                        $brl = CHtml::$beforeRequiredLabel;
                        $label = CHtml::activeLabelEx($model, $attribute, $htmlOptions);

                        $label = str_replace($arl, '', $label);
                        $label = str_replace($brl, '', $label);
                        $label_text = strip_tags($label);
                        $label_html = str_replace($label_text, '', $label);
                        $label_html = str_replace('</label>', '', $label_html);

                        return $label_html.$brl.$label_text.':'.$arl.'</label>';
                }
                else return str_replace('</label>', ':</label>', CHtml::activeLabelEx($model, $attribute, $htmlOptions));
        }
Asterisk NOT required, but colon on the contrary...

In addition to above function, I wrote another one that removes everything related to field being required (i.e. asterisk and CSS styling) leaving colon in place. Removing required attributes from label is a build-in feature of form generator, you just need to change labelEx function from your view to simple label one. But then, again, you also loose colon. For those that need it at the end of label, but not the required attributes, here is a function for this purpose:

public function labelNA($model, $attribute, $htmlOptions = array())
	{
		if ($model->isAttributeRequired($attribute))
                {
                        $arl = CHtml::$afterRequiredLabel;
                        $brl = CHtml::$beforeRequiredLabel;
                        $label = CHtml::activeLabelEx($model, $attribute, $htmlOptions);

                        $label = str_replace($arl, '', $label);
                        $label = str_replace($brl, '', $label);
                        $label = str_replace(' class="required"', '', $label);
                        $label_text = strip_tags($label);
                        $label_html = str_replace($label_text, '', $label);
                        $label_html = str_replace('</label>', '', $label_html);

                        return $label_html.$label_text.':</label>';
                }
                else return str_replace('</label>', ':</label>', CHtml::activeLabelEx($model, $attribute, $htmlOptions));
        }
Textual information of maximum number of characters

And here is overloaded version of CActiveForm.textField that adds simple span after input box with information on how many characters may be entered to it, with respecting plural form of number endings:

const TEXT_FIELD_EX_BEGIN = '(enter up to {size} ';
        const TEXT_FIELD_EX_EXPR = 'n==1#char|n>=1#chars';
        const TEXT_FIELD_EX_END = ')';

        public function textFieldEx($model, $attribute, $htmlOptions = array())
        {
                if(isset($htmlOptions['maxlength']))
                {
                        $max = $htmlOptions['maxlength'];

                        $transl = self::TEXT_FIELD_EX_BEGIN.$max.' ';
                        $transl.= CChoiceFormat::format(self::TEXT_FIELD_EX_EXPR, $max);
                        $transl.= self::TEXT_FIELD_EX_END;

                        $textFieldAdd = ' <span class="text_field_add">'.$transl.'</span>';
                }
                
                return CHtml::activeTextField($model, $attribute, $htmlOptions).$textFieldAdd;
        }

The above example might not be perfect as grammar in English is quite easy for doing plural form (but not that easy, look into CCodeModel::pluralize(). But in other languages (for example in my native Polish), it is so complicated, that even regular expressions can't handle it! :)

Final words

I understand that the above code is far from perfect. It was written very quickly, so everyone please feel free to edit and correct it.