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