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(); ?>