admin管理员组

文章数量:1279175

In my Angular 8 ponent, 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 ponent 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 ponent 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 ponent 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 ponent 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 ponent loads?

Here is my stackblitz ponent.ts

In my Angular 8 ponent, 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 ponent 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 ponent 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 ponent 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 ponent 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 ponent loads?

Here is my stackblitz https://stackblitz./edit/angular-version-yeg27j?file=src%2Fapp%2Fapp.ponent.ts

Share Improve this question edited Nov 11, 2020 at 15:42 Boann 50k16 gold badges124 silver badges152 bronze badges asked Nov 11, 2020 at 2:38 eutychos tfareutychos tfar 1791 gold badge2 silver badges9 bronze badges 3
  • It may help you Ref: stackoverflow./questions/33700266/… – Arunkumar Ramasamy Commented Nov 11, 2020 at 3:23
  • @ArunkumarRamasamy i have updated my post with stakcblitz – eutychos tfar Commented Nov 11, 2020 at 3:44
  • I don't understand why do you need (ngModelChange) to fire when setting the value initially. Can you explain to me why? – Saiyaff Farouk Commented Nov 11, 2020 at 7:55
Add a ment  | 

4 Answers 4

Reset to default 3

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 ponent class.

In the ponent 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.

You can use value instead of ngValue in you option elements. And assign t.code instead of t to the value attribute.

<select  (ngModelChange)='termSelectChanged($event)' [ngModel]="selected">
  <option [value]="t.code" *ngFor='let t of termsColl'>{{t?.code}}</option>
</select>

Reference: https://angular-version-xkjuff.stackblitz.io

termsColl has data but the code line this.selected = this.termsColl[1]; does not change the selected option to the first element in the drop down.

Because you are using propery binding [ngModel]="selected", not two-way data binding.

[(ngModel)]="selected" is for two-way binding, and the syntax is pound from:

[ngModel]="selected" and (ngModelChange)="selected = $event"

Also, the value of selected should be the value which is available in dropdown, i.e

ngOnInit(){
 
 this.selected = this.termsColl[1].code

}

Below code would work for you:

<select  [(ngModel)]="selected" (change)="onSelection()">
  <option  *ngFor='let t of termsColl' [value]="t.code" [selected]="selected === t.code">{{t?.code}}</option>
</select>

You might also want to refer this https://stackoverflow./a/63192748/13596406

本文标签: javascriptWhy does ngmodelChange event not fire when component loads on a dropdownStack Overflow