Working with a newly created Angular 11 project.
app.component.html
<div *ngFor="let i of getItems()">
<select (change)="onSelectionChange($event.target.value)">
<option></option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
</select>
</div>
app.component.ts
export class AppComponent {
getItems(): any[] {
return [{a: 1}, {a: 2}, {a: 3}, {a: 4}];
}
onSelectionChange(event) {
console.log(event);
}
}
Everything seems to be ok. Four select boxes are visible each one with an empty value and four integers in the dropdown list. The strange thing is that when I open a dropdown and click to select a value, the onSelectionChanged() event gets triggered but the selected value does not change in the select.
The select components start working as expected if I change the getItems() method to return plain numbers instead of objects, as follows:
getItems(): any[] {
return [1, 2, 3, 4];
}
Moreover, I get the correct behaviour also removing the (change) event from the HTML markup (in this case the event won't be triggered).
I'm working with these dependencies
"dependencies": {
"@angular/animations": "~11.0.1",
"@angular/common": "~11.0.1",
"@angular/compiler": "~11.0.1",
"@angular/core": "~11.0.1",
"@angular/forms": "~11.0.1",
"@angular/platform-browser": "~11.0.1",
"@angular/platform-browser-dynamic": "~11.0.1",
"@angular/router": "~11.0.1",
"rxjs": "~6.6.0",
"tslib": "^2.0.0",
"zone.js": "~0.10.2"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.1100.2",
"@angular/cli": "~11.0.2",
"@angular/compiler-cli": "~11.0.1",
"@types/jasmine": "~3.6.0",
"@types/node": "^12.11.1",
"codelyzer": "^6.0.0",
"jasmine-core": "~3.6.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~5.1.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.0.3",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.5.0",
"protractor": "~7.0.0",
"ts-node": "~8.3.0",
"tslint": "~6.1.0",
"typescript": "~4.0.2"
}
Use trackBy to resolve the issue. Each time change detection is triggered, angular re-renders the entire template and i gets evaluated to the first object always.
.html
<div>
<select (change)="onSelectionChange ($event.target)">
<option *ngFor="let i of getItems(); trackBy:identify"
value="{{i.value}}">{{i.label}}</option>
</select>
</div>
.ts
identify(index, item) {
return item.label;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With