7

I have following data :

Array
(
    [category] => Array
        (
            [0] => d
            [1] => 100
            [2] => 100
            [3] => 100
        )

    [volume] => Array
        (
            [0] => 100
            [1] => 100
            [2] => 100
        )

    [urgency] => Array
        (
            [0] => 100
            [1] => 100
            [2] => 100
        )

    [importance] => Array
        (
            [0] => 100
            [1] => 100
            [2] => 100
        )
)

And I created DynamicModel for it with rules "each value should be integer" (added in 2.0.4).

$view_model = DynamicModel::validateData(compact('category', 'volume', 'urgency', 'importance'), [
        [['category', 'volume', 'urgency', 'importance'], 'each', 'rule' => ['integer']],
    ]);

In view I have:

    <?= $form->field($model, 'category[0]')->textInput() ?>
    <?= $form->field($model, 'category[1]')->textInput() ?>
    <?= $form->field($model, 'category[2]')->textInput() ?>
    ...
    <?= $form->field($model, 'importance[2]')->textInput() ?>

Problem is, when I submit form with "d" in first input, I have errors on each "category" input: enter image description here

What I do wrong?

15
  • Each validator validates array values associated with specific model attribute. So if one of array values doesn't validate the whole attribute considered invalid. In other words you don't have information which array element have caused validation error. Commented Oct 18, 2015 at 15:09
  • @aalgogiver of course he can get information about which array element have caused validation error. It is easily possible via: $view_model->getErrors(). Commented Oct 18, 2015 at 15:23
  • @aalgogiver So it is right behaviour of the framework? Commented Oct 18, 2015 at 15:44
  • Yes, error belongs to attribute. If you had an array of models than each model could have its own error on id field , for example. Commented Oct 18, 2015 at 16:52
  • @aalgogiver You mean this: yiiframework.com/doc-2.0/guide-input-tabular-input.html ? Commented Oct 18, 2015 at 17:01

2 Answers 2

3

You can use Each validator Info: This validator has been available since version 2.0.4.

[
    // checks if every category ID is an integer
    ['categoryIDs', 'each', 'rule' => ['integer']],
]

This validator only works with an array attribute. It validates if every element of the array can be successfully validated by a specified validation rule. In the above example, the categoryIDs attribute must take an array value and each array element will be validated by the integer validation rule.

rule: an array specifying a validation rule. The first element in the array specifies the class name or the alias of the validator. The rest of the name-value pairs in the array are used to configure the validator object.
allowMessageFromRule: whether to use the error message returned by the embedded validation rule. Defaults to true. If false, it will use message as the error message.

Note: If the attribute value is not an array, it is considered validation fails and the message will be returned as the error message.
Sign up to request clarification or add additional context in comments.

Comments

0

This answer is applicable to ajax request scenarios

In your controller

use yii\base\Model;
use yii\widgets\ActiveForm;
use yii\web\Response;

public function actionCreate()
{
    $models = [
        'model1' => new Category, 
        'model2' => new Category, 
    ];

    if (Yii::$app->request->isAjax && Model::loadMultiple($models, Yii::$app->request->post())) {
        Yii::$app->response->format = Response::FORMAT_JSON;

        $validate = [];
        $validate = array_merge(ActiveForm::validateMultiple($models), $validate);
        // If you need to validate another models, put below.
        // $validate = array_merge(ActiveForm::validate($anotherModel), $validate);

        return $validate;
    }

    if (Model::loadMultiple($models, Yii::$app->request->post())) {
        foreach($models as $key => $model) {
            $model->save();
        }
    }

    return $this->render('create', [
        'models' => $models,
    ]);
}

In your view

<?php 
    $form = ActiveForm::begin([
        'enableClientValidation' => false, 
        'enableAjaxValidation' => true, 
    ]);
?>

<?= $form->field($models['model1'], '[model1]name')->textInput(); ?>
<?= $form->field($models['model2'], '[model2]name')->textInput(); ?>

<?= Html::submitButton('Create') ?>

<?php ActiveForm::end(); ?>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.