Saving CMaskedTextField to model without "-", "_", "/" - just pure strings... placeholders I think...

Before the problem came out… I was inputting some values into the simple form fields and after saving form, they were inserted/updated to the model.

For example in the field "Address code" user was entering 5 digits: 01180. And to the database tha string value "01180" (can start with zero) was inserted/updated.

Once I was using jQuery masking feature which is nice, so I though to apply it again. It was really nice and easy, and user was clicking the same keys, but as the result in text value he had 01-180, which is used officially in Poland (zip code). The same with other fields, example: telephone number which is written with (brackets) and "-" pauses.

And my concern is as follows:

I prefer saving this values as strings without brackets and pauses and spaces. Just pure alphanumeric strings, because it will be easier to operate on them. I would like user to have possibility to enter 01-180 on the form with masking plug-in but when I save form to the database I would like to save unmasked value "01180".

But when I applied jQuery mask plug-in and tried to save form, instantly errors occurred. Off course text field length increased:

So my question is: can I unmask these CMaskedTextField values "on the fly" before saving them? Remove the placeholders? In controller? In some filter? Would it be great effort to do so? Also what about fetching them into the masked form, for example in database I have "01180", but on form I want it to load as "01-180" (form is already masked) and vice versa I want to save 01-180 as "01180".

OR

Should I now change in model.php length of every masked field, and also change database accordingly (resize columns) - doesn’t sound nice… also validation rules would need update

Thanks in advance

Tom

You can implement the beforeValidate function, in order to strip all this characters.

The only bad point is that the user will see in the form, in case of error, the cleaned string.

In your model:




public function beforeValidate()

{

  [..strip your placeholders..]

  return parent::beforeValidate();

}



Indeed the function beforeValidate() is working (I strip placeholders in there), now I don’t get info that address_code is wrong (it passes validation because stripped length is 5), but the CMaskedTextField is cleared, unlike other fields which passed validation and stay filled with the entered values.

Can yii leave the masked value in the CMaskedTextField?

Or maybe it will be better to save the CMaskedTextField as is to database? How do you think, but then I would have to change database columns, change model code etc…

This is the expected behavior: after stripping the placeholder the text is correct, and so is correctly saved on database.

If you want to strip before save you can do this stripping in the before save function (but you have to rewrite your rules).

I think that the best solution is how is working now:

690-840-790 => stripped => 690840790 => isValid => saved

This is intuitive, I think

Well, I’m not sure if I understand this… now in the function beforeValidate():




public function beforeValidate()

{

$this->address_code=substr($this->address_code,0,2).substr($this->address_code,2,3);

return parent::beforeValidate();

}



I strip placeholders (so 11-111 becomes "11111") to get pure string of length defined in model. So it passes validation. It is not saved to database anyway, since other values do not pass validation:

And the CMaskedTextField gets cleared what I don’t want. What can I do to assure that masked string still will be in CMaskedTextField in my case?

Any solution for this case?

Not easy, but if you want this to work… one solution would be:

first - write a custom validator where you can check this values… and leave them in the input form… so that the validation works and values remains on the form

second - you extend beforSave() and afterFind()… in beforeSave() you strip the dashes… in afterFind() you add the dashes…

Thanks mdomba

Well it sounds a bit complex for my current yii knowledge, so I think I change model and database instead. Thanks anyway.

The string 690-120-139 is not that "bad" in database (stripped is always nicer), but phone numbers I want to mask in the way: (22) 644 22 22…

Assuming that now I have beforeValidate():


public function beforeValidate()

{

$this->address_code=substr($this->address_code,0,2).substr($this->address_code,2,3);

return parent::beforeValidate();

}

and stripped string passes validation, but then disappears from CMaskedTextField after some other values don’t pass validation.

So does my current piece of work with beforeValidate() fit any of your proposals? Can you give me more details or point me to yii docs/examples?

Thanks

Tom

beforeValidate is not good for you as it removes the value from the input box, and that is not good for user experience…

So if you will adjust the database and you don’t need to remove anything… then it’s just the validation that you need to solve…

As I wrote above you can write a custom validator… a validator can be a name of a method in the class or a complete new class… check the docs - http://yiiframework.com/doc/guide/1.1/en/form.model#declaring-validation-rules

There you can check whatever you need… and leave the entered value as it is… so it will be displayed to the user…

Well, eventually I resized columns in database and updated validation rules in model so masked strings could fit. Quickest solution, however not that perfect as saving stripped values. Unfortunately I could not find examples of how to apply custom validator to achieve my goal. Thanks for interest anyway.

Ressurecting the old thread for a good reason, I hope :)

My solution:




protected function beforeValidate() {

	$old = array();


	$old['attribute'] = $this->attribute;

	$this->attribute = preg_replace('/[^\d]/', '', $this->attribute);


	$result = parent::beforeValidate();


	if (!$result) {

		$this->attribute = $old['attribute'];

	}


	return $result;

}



Ressurecting #2

I decide to use hidden field for real value and CMaskedTextField only for beauty representation of phone number input. In ‘comleted’ JS function I set cleaned from spaces value to hidden “real” field.

To prevent passing CMaskedTextField add ‘number-formScript’ script.




<?php

	Yii::app()->clientScript->registerScript('number-formScript', "

		$('#number-form').submit(function() {

		    $(':input[name=\"NumberForm_n_name\"]').attr('disabled', true);

		});

	");

?>


..........


    <input type="hidden" name="n" id="NumberForm_n">  

    <span class="prefix7">+7</span><?php    

        $this->widget('CMaskedTextField', array(

            'id'=>'NumberForm_n_name',

            'mask' => '999 999 99 99',

            'placeholder' => ' ',

            'completed' => 'function(){ $("#NumberForm_n").val( $("#NumberForm_n_name").val().replace(/ /g,"") ); }',

            'name' => 'NumberForm_n_name',

            'htmlOptions' => array(

                'placeholder'=>'901 111 11 11',

                'size'=>'10',

                'maxlength'=>'10'

            )

        ));

        ?><input type="submit" value=" ">


..........