Angular 4 - Reactive Forms - выберите элемент в списке из объекта, на который нет ссылок в этом списке - проблема с отслеживанием?
Я конвертирую код Angular 1.6 в Angular 4, и у меня есть проблема со списком элементов. Код в Angular 1.6:
<select ng-model="$ctrl.level" ng-options="item as item.label for item in $ctrl.referentiel.levels | orderBy : 'index' track by item.id" id="childLevel" name="childLevel" class="size-xl" >
<option value="">Select</option>
</select>
Уровень объекта не указан в моем списке, поскольку этот список загружается с использованием объекта referentiel.levels. Но соответствие между элементами моего списка и моим уровнем объекта выполняется благодаря trackby. Поэтому, когда мой объект Level загружен, элемент выбирается в списке.
Теперь я пытаюсь преобразовать этот код с помощью Reactive Forms. В моем HTML-коде у меня есть:
<select formControlName="levelControl" id="levelSelect" name="levelSelect" class="size-xl">
<option [ngValue]="null">Select</option>
<option *ngFor="let level of referentiel.levels;trackBy:identify" [ngValue]="level">{{level.label }}</option>
</select>
И в моем компоненте я имею в методе OnInit:
(<FormControl>this.myForm.controls.levelControl).setValue(this.level);
И метод идентификации прост:
identify(index,item){
return item.id;
}
Но ассортимент другой. Когда я устанавливаю значение своего элемента управления, используя свой уровень объекта, элемент с таким же идентификатором в списке не выбирается.
Я нашел решение, но я не понимаю, почему оно не работает. Мой обходной путь - написать этот код в HTML:
<option *ngFor="let level of referentiel.levels;trackBy:identify" [ngValue]="level.id">{{level.label }}</option>
И в моем машинописном файле:
(<FormControl>this.myForm.controls.levelControl).setValue(this.level.id);
Итак, теперь это работает: мой элемент выбран в списке.
Я не понимаю разницу между двумя версиями Angular в этом случае. Может быть, я что-то пропустил...
Спасибо за вашу помощь.
1 ответ
Я не вижу, что вам понадобится trackBy
здесь, если вы не хотите его использовать. Но это не имеет никакого отношения к тому, почему ваш вариант по умолчанию не работает.
Почему это работает с level.id
потому что это строка (число?), тогда как level
это объект, который не имеет ссылки на ваш массив, поэтому он не может быть распознан из списка.
Поскольку вы используете Angular 4, у нас теперь есть новая директива [compareWith]
где мы можем сравнить некоторые свойства из вашего level
например id
, Сравните это с массивом и найдите совпадение. Так что вы можете сделать следующее:
<select formControlName="levelControl" [compareWith]="compare"
id="levelSelect" name="levelSelect" class="size-xl">
<option value="">Select</option>
<option *ngFor="let level of referentiel.levels" [ngValue]="level">
{{level.label }}
</option>
</select>
составная часть:
compare(val1, val2) {
return val1.id === val2.id;
}
Также обратите внимание, что я изменился
<option [ngValue]="null">Select</option>
в
<option value="">Select</option>
так что Angular не пытается сравнить с null
значение. Это может привести к ошибке.