Automatic maxlength attribute for input fields (type text or password)

Currently the maximum length for a text field is set in 3 places:

  1. in the data base (i.e. name varchar(255) NOT NULL )

  2. in the AR rules (i.e. array(‘name’,‘length’,‘max’=>255) )

  3. in the view (i.e. CHtml::activeTextField($model,‘name’,array(‘maxlength’=>255)) )

Contrary to that the "required" property is set in only 2 places

  1. in the data base (i.e. name varchar(255) NOT NULL )

  2. in the AR rules (i.e. array(‘name’,‘required’) )

When using MyCHtml::activeLabelEx($model, ‘name’), then the method CModel::isAttributeRequired() is called to determine if a “*” should be displayed next to the label. (CModel::isAttributeRequired() checks the AR rules.)

I suggest the following Yii enhancement:

The maxlength attribute for inpute fields should also be determined from the rules, this could be done like this:

Add a new method to CModel:




public function getAttributeMaxLength($attribute,$scenario='') {

    $validators=$this->getValidatorsForAttribute($attribute,$scenario);

    foreach($validators as $validator) {

        if($validator instanceof CStringValidator)

            return $validator->max;

    }

    return null;

}



Change 2 methods in CHtml:




public static function activeTextField($model,$attribute,$htmlOptions=array()) {

    if(!isset($htmlOptions['maxlength']) && ($maxlength = $model->getAttributeMaxLength($attribute))) {

        $htmlOptions['maxlength'] = $maxlength;

    }

    self::resolveNameID($model,$attribute,$htmlOptions);

    self::clientChange('change',$htmlOptions);

    return self::activeInputField('text',$model,$attribute,$htmlOptions);

}


public static function activePasswordField($model,$attribute,$htmlOptions=array()) {

    if(!isset($htmlOptions['maxlength']) && ($maxlength = $model->getAttributeMaxLength($attribute))) {

        $htmlOptions['maxlength'] = $maxlength;

    }

    self::resolveNameID($model,$attribute,$htmlOptions);

    self::clientChange('change',$htmlOptions);

    return self::activeInputField('password',$model,$attribute,$htmlOptions);

}



I am already using this, it works well and saves a lot of writing when doing some changes to AR attributes. It would be nice if it was incorporated into the Yii core.

What do you think?

Great enhancement, but I personally think that there is no need to limit client-side input length, because it can be done via server-side validation.

If maxlength can be determined from db structure, it’d be even better!

To just have all this defined in the DB only you could override the rules() function making standard rules based on the meta data of the table. I have not got around to do that yet, also Yii 1.1 will introduce some major changes that would require to redo it.

You are right, server validation is always necessary, though I think it’s nice if you have an input field that does not let you enter more letters than allowed (a postcode for example).

I’m not quite sure if this is desired by most of the users. If we choose to implement it, maxlength will probably be based on db column size rather than validation rule setting. In general, we don’t like special manipulation of specific rules.

I don’t like the idea of client-side validation of max length. I am afraid a user might try to for example type “John Doe” when only 6 characters are allowed and it comes out to “John D”. Then the user presses submit not realizing what he entered in the form. Not good…

I don’t like yiic putting a maxlength on the forms in such a redundant way… And I don’t think rules like this one should be treated specially with a getAttributeMaxLength() method either.

Maybe something more generic, like this would be nice:


getAttributeRule($attribute, $ruleName, $scenario)

returns either an instance of the configured rule or an array of the rule's configurations

EDIT: I just realized this is an old topic… oops… but I wrote this so I’m going to submit it

Errors are part of the validation process. A tooltip may come up or something similar should happen in this case.

I agree to sluderitz request. Max-length actually is redundant and reduces our textfields reusability.

I think client-side limitation is VERY necessary. Users have to know their input limits, reducing their time to submit a form. I don’t like my users having to submit a form to discover input limits.

I don’t understand Jonah, as the ‘maxlength’ attribute of an input doesn’t allow the user to submit data greater than the specified.

With sluderitz changes are nice, we can easily reuse our textfields with the correct max-length value!

Then choose your input limits carefully! :)

It doesn’t care if you have choose your limits carefully.

Users commomnly tries to go beyond the form limits. If I have an ‘address’ column with 80 characters limit, I will have some users trying to put 100 characters. If I expand it to 100 characters, they will try to insert 120 and so on.

If you have a ‘description’ field with 200 characters length, you must avoid the user to insert 1000 characters on the field and just discover on submit that he is just enabled to insert 200. :confused:

You better provide feedback to your users, so they will know they typed 150 characters out of 200.

I agree, you should implant some sort of feedback if you have a max length in place on the client-side. But I don’t think yiic should put this in place with it’s default templates… I think it should be left to the user to extend yiic if they want this

I think the best solution would be Jonahs idea having a new general method:

getAttributeRule($attribute, $ruleName, $scenario) returning an instance of the configured rule or NULL if the rule does not exist.

Later this came to my mind as well, its the most flexible approach. You could then find out any rule configuration you need and use it in CHtml. Maybe the isAttributeRequired() method could then be ommited as well.