Yii2: Validation in form with two instances of sam

2019-02-26 15:47发布

问题:

I have a model Booking with the fields shipping_address and billing_address, both of the model Address. I now want to print them to the same form which basically works pretty well, the problem is the fields of both models have the same IDs. For example the field "zip" in the shipping_address has the id "zip" and the "zip" in billing_address also has "zip" as its id.

If I now fill out the form, it validates both of the fields at the same time while only one of them is actually true.

I've already changed the names of the fields to Shippping_Address['zip'] and Billing_Address['zip'] therefore the controller is able to recognize both models.

Here's how the fields are printed:

<?= $form->field($billing_address, 'address_line_1')->textInput(['maxlength' => 45, 'name'=> 'Billing_Address[address_line1]']); ?>
<?= $form->field($billing_address, 'address_line_2')->textInput(['maxlength' => 45, 'name'=> 'Billing_Address[address_line2]']) ?>
<?= $form->field($billing_address, 'zip')->textInput(['maxlength' => 11, 'name'=> 'Billing_Address[zip]']) ?>
<?= $form->field($billing_address, 'city')->textInput(['maxlength' => 45, 'name'=> 'Billing_Address[city]']) ?>
<?= $form->field($billing_address, 'country')->textInput(['maxlength' => 45, 'name'=> 'Billing_Address[country]']) ?>

<?= $form->field($shipping_address, 'address_line_1')->textInput(['maxlength' => 45, 'name'=> 'Shipping_Address[address_line1]']); ?>
<?= $form->field($shipping_address, 'address_line_2')->textInput(['maxlength' => 45, 'name'=> 'Shipping_Address[address_line2]']) ?>
<?= $form->field($shipping_address, 'zip')->textInput(['maxlength' => 11, 'name'=> 'Shipping_Address[zip]']) ?>
<?= $form->field($shipping_address, 'city')->textInput(['maxlength' => 45, 'name'=> 'Shipping_Address[city]']) ?>
<?= $form->field($shipping_address, 'country')->textInput(['maxlength' => 45, 'name'=> 'Shipping_Address[country]']) ?>

Edit: After implementing the answer of tony:

<?= $form->field(
            $shipping_address,
            'address_line_1',
            [
                'selectors' => [
                    'input' => '#shipping-address_line_1',
                    'container' => '.shipping-address_line_1'
                ],
                'options' =>
                    ['class' => 'shipping-address_line_1']
            ])->textInput([
                'maxlength' => 45,
                'name'=> 'Shipping_Address[address_line1]',
                'id'=>'shipping-address_line_1',
            ]); ?>

I also changed the container class because it was the same as the one the other field had. Now the second field (with the code as shown above) is working perfectly. The problem is, the first field (with the code unchanged) is not validating anymore.

How could this be solved?

回答1:

Because you use one model class for generating two sets of inputs at one page, yii2 generates identical clientValidation rules for both of them. To separate validation you need to set id attribute for each input that required validation in each of this sets manually. For your zip input field the solution will be next (edited according to latest comments):

//Billing
$form->field($billing_address, 'zip', 
[
    'selectors' => [
        'input' => '#billing-zip',
        'container' => '#billing-container',
    ],
    'options' => ['id' => 'billing-container'],
])->textInput(['maxlength' => 11, 
               'name'=> 'Billing_Address[zip]', 
               'id'=>'billing-zip']); 

//Shipping
$form->field($shipping_address, 'zip', 
[
    'selectors' => [
        'input' => '#shipping-zip',
        'container' => '#shipping-container',
    ],
    'options' => ['id' => 'shipping-container'],
])->textInput(['maxlength' => 11, 
               'name'=> 'Shipping_Address[zip]', 
               'id'=>'shipping-zip']);

As you can see we added custom id attribute in textInput options, and set corresponding selector for js validation in field options. Read about selectors property