iKan
iKan

Reputation: 1

Yii 2.0 Scenarios - Dynamic Validation

I have a situation where I would like to validate a textbox input; however, the type of validation is dependent on the selection of a dropdown list on that page (there would be multiple of each of these on a page). So, the textbox can take a string, an integer, a date, etc. and the user must select something from the dropdown list that would tell me what the data type has to be that the user will enter.

I was thinking to use scenarios for this; however, the textbox is 1 field in my model/database that accepts a string at the database level (I just don't want the user to enter a string when an integer is appropriate regardless of how I handle on the backend).

Here's what I was thinking so far, but I don't know if this is the best route to take for this problem? Also, if I can use the scenarios for this then how do I specify in the view the rules for the textbox when a user selects something that requires i.e..date input? Is there a way that I could call the rule with Ajax on click of dropdown list?? Sorry, this is probably a little too broad a question, but I'm new to Yii and I'm just trying to get headed down the right path with this. Thank you!

public function scenario()
{
    return[
            'isstring' => ['filter_value'],
            'isint' => ['filter_value'],
            'isdate' => ['filter_value'],
            'isfloat' => ['filter_value'],
            'all' => ['freq_int', 'freq_unit_fk', 'filter_field_fk',   'arithmetic_op', 'logic_op', 'filter_value']
    ];

}
public function rules()
{
    return [
        [['freq_int', 'freq_unit_fk'], 'integer', 'message' => 'Integer'],
        [['freq_int', 'freq_unit_fk', 'filter_field_fk', 'arithmetic_op'], 'required'],
        [['logic_op'], 'safe'],
        [['filter_value'], 'integer', 'on' => 'isint'],
        [['filter_value'], 'string', 'min' => '2', 'max' => '75', 'on' => 'isstring'],
        [['filter_value'], 'trim', 'on' => 'isstring'],
        [['filter_value'], 'number', 'on' => 'isfloat'],
        [['filter_value'], 'date', 'on' => 'isdate']
        ];
}

Ok, so to give more detail, and I've decided to drop the idea of having the validation set based on a dropdown selection for now. Instead, it just needs to get set based on a value that I'm getting from the database when the page gets loaded. I have a partial view file called '_settings.php' and it gets rendered as a modal through a view file called 'manage.php'. Here is the code in _settings.php that displays the text boxes that I'm trying get the validation to work on:

foreach($crystalfields as $field)   

        {

            if($field['custom'] == 4)
            {           
                        $datatype = $model->getDatatypeName($field['datatype']);                    
                        $filterstring = $form->field($model, 'filter_value', ['inputOptions' => ['id' =>'filterval'.$crystalid.'-'.$field['fieldid']]])
                                                ->textinput(['name' => 'filterval'.$crystalid.'-'.$field['fieldid']])
                                                ->label(false);         
                        $filterstrings = $filterstrings.'<div class="form-group">
                                                <div class="form_group row">
                                                    <label for="filterval'.$crystalid.'-'.$field['fieldid'].'" class="col-sm-3 control-label">'.$field['fieldname'].'</label>
                                                        <div class="col-sm-6 pull-right">'.$filterstring.'</div>
                                                </div>
                                            </div>';

            }

...there is more to the foreach loop that is irrelevent. Basically, what I want to do is have the validation for this text box be set based on the result of the method $model->getDatatypeName($field['datatype']) ... method is part of my model where the validation rules exist; however, the primary key $field['datatype'] that I'm passing to this method is based on a query that is joining many related tables in my view model ..$model in this case. So when this method passes back 'string' I want to set the validation accordingly. There can be multiple of these text boxes within the modal that each have different validation types but are attached to the same 'filter_value' field each time.

Upvotes: 0

Views: 2057

Answers (1)

Blizz
Blizz

Reputation: 8400

I think the easier solution here would be to use the when-functionality. This gives you fine control over whether the rule should be triggered:

public function rules()
{
    return [
        [['freq_int', 'freq_unit_fk'], 'integer', 'message' => 'Integer'],
        [['freq_int', 'freq_unit_fk', 'filter_field_fk', 'arithmetic_op'], 'required'],
        [['logic_op'], 'safe'],
        [['filter_value'], 'integer', 'when' => function ($model) {return $model->logic_op == 'integer'; }],
        [['filter_value'], 'string', 'min' => '2', 'max' => '75', 'when' => function ($model) {return $model->logic_op == 'string'; }],
        [['filter_value'], 'trim', 'when' => function ($model) {return $model->logic_op == 'string'; }]],
        [['filter_value'], 'number', 'when' => function ($model) {return $model->logic_op == 'float'; }]],
        [['filter_value'], 'date', 'when' => function ($model) {return $model->logic_op == 'date'; }]]
    ];
} 

Upvotes: 1

Related Questions