简体   繁体   中英

Angular : bootstrap-modal value doesn't bind on first time

I am having an issue with a modal binding ( parent to child ) I have an array which I fill from a web service. The Array is then passed to modal. The array is empty on first call, but not on following calls and on click I get [n-1] index value everytime instead of [n] index value. What can be the reason for this ?

Child Component

car-detail.html

<div class="modal-body">
  <input [(ngModel)]="car.Id" type="number">
  <input [(ngModel)]="car.make" type="string">
</div>

Car-detail-component.ts

export class CarDetailComponent implements OnInit {
  @Input() public car;
  constructor(private appService: AppService,
    public activeModal: NgbActiveModal,
    private route: ActivatedRoute,private location: Location) { }

  ngOnInit() {
  }

Parent Component

car-component.html

 <label *ngFor="let car of carslist" (click)= "getCarDetailsById(car.id);open()">  
                {{car.make}}
                                <br/>
              </label>

I get the id and pass it to a web service call and I open the modal.

**car.component.ts**

carDetailsList : any =[];

 public getCarDetailsById(id:number):Car[]{
      this.appService.getCarDetailsById(id).subscribe(
        car =>{

          this.carDetailsList=car;
          for (let i = 0; i < this.carDetailsList.length; i++) {
            console.log(car.make);
          }
        }
      );

      return this.carDetailsList;
      }

On first call, array is empty, not on subsequent calls. I get the previous car details each time when the modal opens. Thanks for the help.

You are opening the modal before your service returns the value. You should open the model inside the subscribe method. Thats why you are not getting the value first time, on subsequent calls you always gets the old value. Remove the open() from your parent html template.

public getCarDetailsById(id:number):Car[]{
    this.appService.getCarDetailsById(id).subscribe( car =>{ 
        this.carDetailsList=car; 
        for (let i = 0; i < this.carDetailsList.length; i++) {
            console.log(car.make);
        } 
        this.open();
        return this.carDetailsList;
    });
}

Your problem is actually that you execute a method asynchronous (the subscription is only executed when the server return the data asked) into a function executed synchronously so your function will end and reach the return before the subscription execution is reached that's why when your modal will pop up the array will be empty on the first call.

public getCarDetailsById(id:number):Car[]{
this.appService.getCarDetailsById(id).subscribe(
// 1 when the server return data the code here is executed
car =>{

  this.carDetailsList=car;
  for (let i = 0; i < this.carDetailsList.length; i++) {

    console.log(car.make);
  }
}
);
// until server return data the execution continue so the return statement is reached before the code after point 1 is executed
// the variable returned will be null in that case.
return this.carDetailsList;

}

try instead to make like this:

async getCarDetailsById(id:number):Promise<Car[]> {
    var asyncResult = await this.appService.getCarDetailsById(id).toPromise();
    console.log('this console.log will be executed once the async call is fetched and the value of the returned promise is stored in asyncResult');
    return asyncResult;
}

then in the returned promise in the .then function bind the returned value in one of your value of type Car[].

and you call the 'getCarsDetailsRecovered' function when you open your modal.

an usefull link about asynchronous calls in angular: link .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM