I am converting Angular 1.6 code to Angular 4 and I have an issue with a list of elements. The code in Angular 1.6 is:
<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>
The object level is not referenced in my list because this list is loaded using the object referentiel.levels. But the matching between the elements of my list and my object Level is done thanks to trackby. So when my object Level is loaded, the element is selected in the list.
Now, I try to convert this code using Reactive Forms. In my HTML code, I have:
<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>
And in my component, I have in the OnInit method:
(<FormControl>this.myForm.controls.levelControl).setValue(this.level);
And the method identify is simple:
identify(index,item){
return item.id;
}
But the comportment is different. When I set the value of my control using my object Level, the item with the same id in the list is not selected.
I found a solution but I don't understand why it is not working. My workaround is to write this code in HTML:
<option *ngFor="let level of referentiel.levels;trackBy:identify" [ngValue]="level.id">{{level.label }}</option>
And in my typescript file:
(<FormControl>this.myForm.controls.levelControl).setValue(this.level.id);
So, now it is working: my item is selected in the list.
I don't understand the difference between the two versions of Angular in this case. Maybe I missed something...
Thanks for your help.
I don't see that you would need the
trackBy
here, unless you want to use it. But it has nothing to do with why your default option is not working.Why it works with
level.id
is because this is a string (number ?) whereaslevel
is an object that has no reference to your array, therefore it cannot be recognized from the list.Since you are using Angular 4, we now have a new directive
[compareWith]
where we can compare some property from yourlevel
, for example theid
. Compare it with the array and find a match. So what you can do is the following:component:
Also notice that I changed
to
so that Angular is not trying to compare to a
null
value. That would throw an error.