In my Angular 8 component, I have added bi-directional binding to a dropdown control.
The view
<select (ngModelChange)='termSelectChanged($event)' [ngModel]="selected">
<option [ngValue]="t" *ngFor='let t of termsColl'>{{t?.code}}</option>
</select>
The component code
export class AppComponent implements OnInit{
public termsColl : Array<DDModel>;
public selected : DDModel;
constructor( private s : DDService ){}
termSelectChanged( event ){
alert('HIT');
}
ngOnInit(){
//service call #1
this.s.getDataForComplexBind().subscribe( data => {
this.termsColl = data;
}, error => error );
//service call #2
this.s.getOtherData( ).subscribe( data => {
//model changes here
this.selected = this.termsColl[1];
}, error => { console.error(error); });
}
}
When the component loads, it executes ngOnInit() and sets the model-bound property Selected with the first element of the array termsColl. termsColl has data but the line this.selected = this.termsColl[1]; does not change the selected option to the first element in the dropdown. In fact, when the component loads, I was expecting it to fire the event ngModelChange but it did NOT fire the event either. I have added an alert() in the code but it did not show when the component loads. It shows only if I select an option from the dropdown. How do I change the code so it will execute the ngModelChange event when the component loads?
Here is my stackblitz https://stackblitz.com/edit/angular-version-yeg27j?file=src%2Fapp%2Fapp.component.ts
I changed the ngModeChange input to DDModel and called your termSelectChanged() from inside the subscribe. I also changed [ngModel] to [(ngModel)]
<select (ngModelChange)='termSelectChanged($event)' [(ngModel)]="selected">
<option [ngValue]="t" *ngFor='let t of termsColl'>{{t?.code}}</option>
</select>
termSelectChanged(selection: DDModel) {
console.log("HIT", selection);
}
ngOnInit() {
this.s.getOtherData().subscribe(
data => {
this.termsColl = data;
this.selected = this.termsColl[0];
this.termSelectChanged(this.selected);
},
error => {
console.error(error);
}
);
}
I can't tell you why changing this.selected from code does not trigger the ngModelChange. Maybe it's because ngModelChange is called in the template.
You can use viewToModelUpdate() of ngModel to update the value and if you want to trigger the ngModelChange. You can find more about it here.
But you need to do the following changes.
In html template:
<select (ngModelChange)='termSelectChanged($event)' [ngModel]="selected" #ngModel="ngModel">
<option [value]="t" *ngFor='let t of termsColl'>{{t?.code}}</option>
</select>
You can see I am adding a reference to the ngModel in template, which I will use it in the component class.
In the component class:
export class AppComponent {
name = "Angular 6";
version = VERSION.full;
public termsColl: Array<DDModel>;
public selected: string;
@ViewChild("ngModel") ngModel: NgModel;
constructor(private s: DDService) {}
termSelectChanged(event) {
this.selected = event;
}
ngOnInit() {
this.s.getOtherData().subscribe(
data => {
this.termsColl = data;
this.ngModel.viewToModelUpdate(this.termsColl[1]);
},
error => {
console.error(error);
}
);
}
}
You can see I am using the ngModel reference to call the viewToModelUpdate with the value, which in return triggers the ngModelChange.
Since you are not using two way binding directly, you have to set the value to the selected variable inside the trigger function termSelectChanged.
Hope this would help you to achieve your requirement.
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