[PROPOSAL] A conditional validator #2406

Closed
gimox opened this Issue Feb 11, 2014 · 32 comments

Comments

Projects
None yet
@gimox
Contributor

gimox commented Feb 11, 2014

If i create a custom validation in model, it not fire if the field is not send (=null) or required.

So if i need somthink like this.

If this field is null then this other field ....
i need to add some logic to controller, but now i have the validation both controller and model and is not so good...

My proposal is to add a conditional validator and make custom validation work if field is null.

@qiangxue

This comment has been minimized.

Show comment
Hide comment
@qiangxue

qiangxue Feb 11, 2014

Member

Did you set skipOnEmpty to be false for your custom validator if you want it to be used all the time?

Member

qiangxue commented Feb 11, 2014

Did you set skipOnEmpty to be false for your custom validator if you want it to be used all the time?

@gimox

This comment has been minimized.

Show comment
Hide comment
@gimox

gimox Feb 11, 2014

Contributor

where i need to set this????

Contributor

gimox commented Feb 11, 2014

where i need to set this????

@qiangxue

This comment has been minimized.

Show comment
Hide comment
@qiangxue

qiangxue Feb 11, 2014

Member

Configure the rule in rules(), something like this: ['name', 'myvalidator', 'skipOnEmpty' => false].

Member

qiangxue commented Feb 11, 2014

Configure the rule in rules(), something like this: ['name', 'myvalidator', 'skipOnEmpty' => false].

@qiangxue qiangxue closed this Feb 11, 2014

@gimox

This comment has been minimized.

Show comment
Hide comment
@gimox

gimox Feb 12, 2014

Contributor

Thanks i try it tomorrow.
Can you add it in model docs?

Contributor

gimox commented Feb 12, 2014

Thanks i try it tomorrow.
Can you add it in model docs?

@cebe cebe added the type:docs label Feb 12, 2014

@cebe cebe reopened this Feb 12, 2014

@cebe cebe closed this in d8508cd Feb 12, 2014

@cebe cebe added this to the 2.0 Beta milestone Feb 12, 2014

@thiagotalma

This comment has been minimized.

Show comment
Hide comment
@thiagotalma

thiagotalma Feb 26, 2014

Contributor

And if the condition is another attribute to be equal to or different from any value?

Contributor

thiagotalma commented Feb 26, 2014

And if the condition is another attribute to be equal to or different from any value?

@cebe

This comment has been minimized.

Show comment
Hide comment
@cebe

cebe Feb 26, 2014

Member

You can check for that in your custom validator...

Member

cebe commented Feb 26, 2014

You can check for that in your custom validator...

@thiagotalma

This comment has been minimized.

Show comment
Hide comment
@thiagotalma

thiagotalma Feb 26, 2014

Contributor

Yes, I can.

But it would be nice being able to do conditional validation in standard validators. :)

Contributor

thiagotalma commented Feb 26, 2014

Yes, I can.

But it would be nice being able to do conditional validation in standard validators. :)

@samdark

This comment has been minimized.

Show comment
Hide comment
@samdark

samdark Feb 26, 2014

Member

I think it may complicate validators a lot.

Member

samdark commented Feb 26, 2014

I think it may complicate validators a lot.

@thiagotalma

This comment has been minimized.

Show comment
Hide comment
@thiagotalma

thiagotalma Feb 26, 2014

Contributor

That would be beautiful:

['state', 'required', 'if' => ['equals' => ['country', Country::USA]]],
['stateOthers', 'required', 'if' => ['notEequals' => Country::USA]],
['mother', 'required', 'if' => [['and' => ['lt' => ['age', 18], 'notEequals' => ['married', Helper::YES]]]]]

Maybe some day ...

Contributor

thiagotalma commented Feb 26, 2014

That would be beautiful:

['state', 'required', 'if' => ['equals' => ['country', Country::USA]]],
['stateOthers', 'required', 'if' => ['notEequals' => Country::USA]],
['mother', 'required', 'if' => [['and' => ['lt' => ['age', 18], 'notEequals' => ['married', Helper::YES]]]]]

Maybe some day ...

@cebe

This comment has been minimized.

Show comment
Hide comment
@cebe

cebe Feb 26, 2014

Member

Rather than introducing a new syntax we could allow using php code:

['state', 'required', 'if' => function($model) { return $model->country == Country::USA; }],
['stateOthers', 'required', 'if' => function($model) { return $model->country != Country::USA; }],
['mother', 'required', 'if' => function($model) { return $model->age < 18 && $model->married != true; }],

Can be written like this for better readability:

public function rules()
{
    $usa = function($model) { return $model->country == Country::USA; };
    $notUsa = function($model) { return $model->country != Country::USA; };
    $child = function($model) { return $model->age < 18 && $model->married != true; };
    return [
        ['state', 'required', 'if' => $usa],
        ['stateOthers', 'required', 'if' => $notUsa], // note that it is not possible to write !$usa
        ['mother', 'required', 'if' => $child],
    ];
}
Member

cebe commented Feb 26, 2014

Rather than introducing a new syntax we could allow using php code:

['state', 'required', 'if' => function($model) { return $model->country == Country::USA; }],
['stateOthers', 'required', 'if' => function($model) { return $model->country != Country::USA; }],
['mother', 'required', 'if' => function($model) { return $model->age < 18 && $model->married != true; }],

Can be written like this for better readability:

public function rules()
{
    $usa = function($model) { return $model->country == Country::USA; };
    $notUsa = function($model) { return $model->country != Country::USA; };
    $child = function($model) { return $model->age < 18 && $model->married != true; };
    return [
        ['state', 'required', 'if' => $usa],
        ['stateOthers', 'required', 'if' => $notUsa], // note that it is not possible to write !$usa
        ['mother', 'required', 'if' => $child],
    ];
}

@cebe cebe reopened this Feb 26, 2014

@cebe cebe added type:feature and removed type:docs labels Feb 26, 2014

@cebe cebe removed this from the 2.0 Beta milestone Feb 26, 2014

@thiagotalma

This comment has been minimized.

Show comment
Hide comment
@thiagotalma

thiagotalma Feb 26, 2014

Contributor

Very, very good! 👍

Avoid the need for us to create inline validators for every different thing.

Contributor

thiagotalma commented Feb 26, 2014

Very, very good! 👍

Avoid the need for us to create inline validators for every different thing.

@qiangxue

This comment has been minimized.

Show comment
Hide comment
@qiangxue

qiangxue Feb 26, 2014

Member

Probably use the name when as if is a reserved word.

Member

qiangxue commented Feb 26, 2014

Probably use the name when as if is a reserved word.

@RusAlex

This comment has been minimized.

Show comment
Hide comment
@RusAlex

RusAlex Feb 26, 2014

Contributor

Thats the most beautyful solution i ever seen.

Contributor

RusAlex commented Feb 26, 2014

Thats the most beautyful solution i ever seen.

@cebe

This comment has been minimized.

Show comment
Hide comment
@cebe

cebe Feb 26, 2014

Member

Thanks :)

Member

cebe commented Feb 26, 2014

Thanks :)

@gimox

This comment has been minimized.

Show comment
Hide comment
@gimox

gimox Feb 26, 2014

Contributor

very interesting solution..

Contributor

gimox commented Feb 26, 2014

very interesting solution..

@samdark

This comment has been minimized.

Show comment
Hide comment
@samdark

samdark Feb 26, 2014

Member

Interesting solution.

Member

samdark commented Feb 26, 2014

Interesting solution.

@cebe

This comment has been minimized.

Show comment
Hide comment
@cebe

cebe Feb 27, 2014

Member

Wasn't that obvious? :-D never used something like that before to be honest ;)

Member

cebe commented Feb 27, 2014

Wasn't that obvious? :-D never used something like that before to be honest ;)

@samdark

This comment has been minimized.

Show comment
Hide comment
@samdark

samdark Feb 27, 2014

Member

Well, it was but I'm too used to anonymous function-less 5.2 :)

Member

samdark commented Feb 27, 2014

Well, it was but I'm too used to anonymous function-less 5.2 :)

@andy5

This comment has been minimized.

Show comment
Hide comment
@andy5

andy5 Feb 27, 2014

Contributor

Can it somehow be applied to a client validation too? Will need to specify a php function + js function fired before field validation.

Contributor

andy5 commented Feb 27, 2014

Can it somehow be applied to a client validation too? Will need to specify a php function + js function fired before field validation.

@cebe cebe added this to the 2.0 RC milestone Feb 27, 2014

qiansen1386 pushed a commit to qiansen1386/yii2 that referenced this issue Mar 9, 2014

drenty added a commit to drenty/yii2 that referenced this issue Mar 19, 2014

qiangxue added a commit that referenced this issue Mar 23, 2014

Merge pull request #2808 from drenty/conditional-validator
Implemented conditional validators (see #2406)

@qiangxue qiangxue modified the milestones: 2.0 Beta, 2.0 RC Mar 23, 2014

@qiangxue qiangxue closed this Mar 23, 2014

@6pblcb

This comment has been minimized.

Show comment
Hide comment
@6pblcb

6pblcb Apr 4, 2014

Missed the discussion (
As a complement.

//string the name attribute, whose value will be used for comparison.
public $dependentAttribute;
//string|integer|array second comparison value
public $compare;
//string the operator of comparison. If $compare is array, $operator can take values, only '==', '===', '!=', '!=='.
public $operator = '==';
//use
['foo', 'required', 'dependentAttribute'=>'bar', 'compare'=>'baz'],

Plus the add-on that can be done enableClientValidation = true

6pblcb commented Apr 4, 2014

Missed the discussion (
As a complement.

//string the name attribute, whose value will be used for comparison.
public $dependentAttribute;
//string|integer|array second comparison value
public $compare;
//string the operator of comparison. If $compare is array, $operator can take values, only '==', '===', '!=', '!=='.
public $operator = '==';
//use
['foo', 'required', 'dependentAttribute'=>'bar', 'compare'=>'baz'],

Plus the add-on that can be done enableClientValidation = true

@cebe

This comment has been minimized.

Show comment
Hide comment
@cebe

cebe Apr 4, 2014

Member

the implemented solution is more flexible as it allows arbitrary conditions.

Member

cebe commented Apr 4, 2014

the implemented solution is more flexible as it allows arbitrary conditions.

@6pblcb

This comment has been minimized.

Show comment
Hide comment
@6pblcb

6pblcb Apr 5, 2014

I do not suggest it, cancel. This supplement. I understand that this is partly duplication. But allows you to make client-side interfaces more flexible.
Perhaps my question is resolved: #1422

6pblcb commented Apr 5, 2014

I do not suggest it, cancel. This supplement. I understand that this is partly duplication. But allows you to make client-side interfaces more flexible.
Perhaps my question is resolved: #1422

@packcode

This comment has been minimized.

Show comment
Hide comment
@packcode

packcode May 5, 2015

Hello guys i am trying to achieve conditional validation but it always returns true,here is my code,
[['amount'], 'required', 'when' => function ($model) {
                    return (($model->shid != 134) || ($model->shid != 76));
                    }, 
                    'whenClient' => "function (attribute, value) {
                    return ($('#dropdownid').val() != 134 || $('#dropdownid').val() != 76);
                    }"
            ],

Can anyone tell me what is i am doing wrong?

packcode commented May 5, 2015

Hello guys i am trying to achieve conditional validation but it always returns true,here is my code,
[['amount'], 'required', 'when' => function ($model) {
                    return (($model->shid != 134) || ($model->shid != 76));
                    }, 
                    'whenClient' => "function (attribute, value) {
                    return ($('#dropdownid').val() != 134 || $('#dropdownid').val() != 76);
                    }"
            ],

Can anyone tell me what is i am doing wrong?

@freezy-sk

This comment has been minimized.

Show comment
Hide comment
@freezy-sk

freezy-sk May 5, 2015

Contributor

@packcode that's because your condition is always true. you want amount to be not required when shid is 134 or 76?

Contributor

freezy-sk commented May 5, 2015

@packcode that's because your condition is always true. you want amount to be not required when shid is 134 or 76?

@packcode

This comment has been minimized.

Show comment
Hide comment
@packcode

packcode May 7, 2015

@freezy-sk yes that is precisely what I want

packcode commented May 7, 2015

@freezy-sk yes that is precisely what I want

@freezy-sk

This comment has been minimized.

Show comment
Hide comment
@freezy-sk

freezy-sk May 11, 2015

Contributor

@packcode so you have to change your condition to be false when its 134 or 76 !($model->shid == 134 || $model->shid == 76) or with equivalent ($model->shid != 134 && $model->shid != 76)

Contributor

freezy-sk commented May 11, 2015

@packcode so you have to change your condition to be false when its 134 or 76 !($model->shid == 134 || $model->shid == 76) or with equivalent ($model->shid != 134 && $model->shid != 76)

@packcode

This comment has been minimized.

Show comment
Hide comment
@packcode

packcode May 11, 2015

Problem solved. Thanks anyways.!!!

Problem solved. Thanks anyways.!!!

@husein-bt

This comment has been minimized.

Show comment
Hide comment
@husein-bt

husein-bt Apr 15, 2016

Hello guys i have the same proplem that occurred with @packcode
Please check it
['end_price', 'required', 'when' => function ($model) { return ($model->start_price!=""); }, 'whenClient' => "function (attribute, value) { if( $('#site-start_price').val() === undefined){ false; }else{ true; } }" ]

Hello guys i have the same proplem that occurred with @packcode
Please check it
['end_price', 'required', 'when' => function ($model) { return ($model->start_price!=""); }, 'whenClient' => "function (attribute, value) { if( $('#site-start_price').val() === undefined){ false; }else{ true; } }" ]

@freezy-sk

This comment has been minimized.

Show comment
Hide comment
@freezy-sk

freezy-sk Apr 15, 2016

Contributor

@husein-bt

['end_price', 'required', 'when' => function ($model) {
    return ($model->start_price != '');
}, 'whenClient' => "function (attribute, value) {
    return ($('#site-start_price').val() != '');
}" ]
Contributor

freezy-sk commented Apr 15, 2016

@husein-bt

['end_price', 'required', 'when' => function ($model) {
    return ($model->start_price != '');
}, 'whenClient' => "function (attribute, value) {
    return ($('#site-start_price').val() != '');
}" ]
@husein-bt

This comment has been minimized.

Show comment
Hide comment
@husein-bt

husein-bt Apr 15, 2016

Thank you @freezy-sk it works
but how can i make compare validation between tow fields in the form

husein-bt commented Apr 15, 2016

Thank you @freezy-sk it works
but how can i make compare validation between tow fields in the form

@freezy-sk

This comment has been minimized.

Show comment
Hide comment
@freezy-sk

freezy-sk Apr 15, 2016

Contributor

@husein-bt sorry but that's off-topic here

Contributor

freezy-sk commented Apr 15, 2016

@husein-bt sorry but that's off-topic here

@husein-bt

This comment has been minimized.

Show comment
Hide comment

Thank you @freezy-sk

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment