Angular 4-реактивные формы-выберите элемент в списке из объекта, не указанного в этом списке - проблема trackby?

я преобразую угловой код 1.6 в угловой 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.уровни. Но соответствие между элементами моего списка и моим уровнем объекта выполняется благодаря trackby. Поэтому, когда загружается мой уровень объекта, элемент выбирается в списке.

теперь я пытаюсь преобразовать этот код, используя Реактивные Формы. В моем 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>

to

<option value="">Select</option>

так что угловой не пытается сравнить с null значение. Это вызовет ошибку.