0

In my form I update more start and end dates from the same model at once. See the simplified form:

<?php $form = ActiveForm::begin(); ?>
    <?php foreach($dates as $i=>$date): ?>
        <?= $form->field($date,"[$i]start"); ?>
        <?= $form->field($date,"[$i]end"); ?>
    <?php endforeach; ?>
</table>
<?= Html::submitButton('Save'); ?>
<?php ActiveForm::end(); ?>

In the model I need to control, if the end date is after the start date:

public function rules() {
    return [
        [['end'], 'compare', 'compareAttribute' =>  'start', 'operator' => '>', 'message' => '{attribute} have to be after {compareValue}.‌'],
    ];
}

I tried to change selectors similarly as described in: Yii2: Validation in form with two instances of same model, but I was not successful. I suppose I need to change the 'compareAttribute' from 'mymodel-start' to 'mymodel-0-start' in the validation JS:

{yii.validation.compare(value, messages, {"operator":">","type":"string","compareAttribute":"mymodel-start","skipOnEmpty":1,"message":"End have to be after start.‌"});}

So, I look for something like:

$form->field($date,"[$i]end", [
    'selectors' => [
        'compareAttribute' => 'mymodel-'.$i.'-start'
    ]
])

Solution

The solution is based on the answer of lucas.

In the model I override the formName() method, so for every date I have a unique form name (based on ID for the existing dates and based on random number for new dates):

use ReflectionClass;
...

public $randomNumber;

public function formName()
{
    $this->randomNumber = $this->randomNumber ? $this->randomNumber : rand();
    $number = $this->id ? $this->id : '0' . $this->randomNumber;
    $reflector = new ReflectionClass($this);
    return $reflector->getShortName() . '-' . $number;
}

The form then looks like this:

<?php $form = ActiveForm::begin(); ?>
    <?php foreach($dates as $date): ?>
        <?= $form->field($date,"start"); ?>
        <?= $form->field($date,"end"); ?>
    <?php endforeach; ?>
</table>
<?= Html::submitButton('Save'); ?>
<?php ActiveForm::end(); ?>
Community
  • 1
  • 1
Antonín Slejška
  • 1,980
  • 4
  • 29
  • 39

1 Answers1

1

Override the formName() method in your model class to make it unique. If you don't want to change your model class, create a subclass of it for the purpose of working for this controller action. After doing this, the html ID and name fields will automatically be unique.

Maddelynne P
  • 614
  • 6
  • 8