javascript - Angular-interpolation fördröjer rendering av vissa värden & hur man tar bort ett objekt från arrayen av TypeScript-objekt


Jag arbetar på en ASP.NET Core - Angular webbapp där jag kan välja en kund som ursprung och hitta avstånd & tid till andra med hjälp av Google Maps Distance Matrix-tjänst. Jag får värdena utan problem (jag tror att konsolloggen visar att fördröjningen inte beror på Google Maps API-anropen/för att hämta värden från en array av objekt) men när jag binder data till mallen med hjälp av Angular-interpolering, blir det fördröjning i att visa avstånds- och tidsvärdena. Det bör också nämnas att tabellen endast visas när knappen klickas - när isFindButtonClicked blir true.

  1. Kan du hjälpa mig att hitta orsaken och åtgärda det?

customers: Array<Customer> = [];
nearbyCustomers: Array<Customer> = [];

getCustomers() {
        this.customerService.getAll()
            .subscribe( result => {
                this.customers = result;
            }, error => {
                this.alertService.error(error._body);
                this.router.navigate(['/home']);
            });
}

ngOnInit() {
        this.getCustomers();
}

Typescript-funktion för att hitta och tilldela distans-/varaktighetsvärden:

findNearbyCustomers(selectedId: number) {
    this.isFindButtonClicked = true;
    this.nearbyCustomers = this.customers;
    var origin = this.customers.find(c => c.id == selectedId);
    var originLatLng = origin.latitude.toString()+","+origin.longitude.toString();
    var service = new google.maps.DistanceMatrixService();

    for (let x = 0; x < this.customers.length; x++) {
            console.log(this.customers[x].id);
            var destinationLatLng = this.customers[x].latitude.toString()+","+this.customers[x].longitude.toString();

            service.getDistanceMatrix({
                origins: [originLatLng],
                destinations: [destinationLatLng],
                travelMode: google.maps.TravelMode.DRIVING
            }, (response, status) => {
                if (status.toString() == 'OK') {
                    console.log('Distance: '+response.rows[0].elements[0].distance.text+', Duration: '+response.rows[0].elements[0].duration.text);
                    this.nearbyCustomers[x].distance = response.rows[0].elements[0].distance.text;
                    this.nearbyCustomers[x].duration = response.rows[0].elements[0].duration.text;
                    console.log('DURATION: '+this.nearbyCustomers[x].duration+', DISTANCE:'+this.nearbyCustomers[x].distance);
                }
            })
    }
}

Delvisa markeringar från Angular-mall:

<tbody>
       <tr *ngFor="let nearbyCustomer of nearbyCustomers">
            <td>{{ nearbyCustomer.businessName }}</td>
            <td>
                <p>{{ nearbyCustomer.streetNumber + ' ' + nearbyCustomer.streetName + ', ' + nearbyCustomer.suburb }}</p>
                <p>{{ nearbyCustomer.city + ' ' + nearbyCustomer.postCode + ', ' + nearbyCustomer.country }}</p>
            </td>
            <td>{{ nearbyCustomer.contactPerson }}</td>
            <td>{{ nearbyCustomer.contactNumber }}</td>
            <td>{{ nearbyCustomer.email }}</td>
            <td>{{ nearbyCustomer.distance }}</td>
            <td>{{ nearbyCustomer.duration }}</td>
      </tr>
 </tbody>
  1. Tidigare har jag också försökt med ett if-uttryck if (this.customers[x].id != this.selectedDeliveryDestinationId) och bara lagt till kunder exklusive den valda (som ursprung) this.nearbyCustomers.push(this.customers[x]); och sedan när jag försökte tilldela ett värde till ett objektattribut och rendera fick jag Cannot set property 'distance' of undefined-fel - det verkar som att jag rörde till indexvärdena. Vad skulle vara det bästa sättet att utesluta en post från arrayen för detta ändamål? Eller, om jag bara kan dölja en specifik rad från HTML skulle det också fungera.

Tack.

Svar #1

Du behöver ngZone i det här fallet för att uppdatera din tabell.

import { NgZone } from '@angular/core';

i konstruktören lägg till: private _ngZone: NgZone sedan i din getDistanceMatrix framgång:

this._ngZone.run(() => {
                this.nearbyCustomers[x].distance = response.rows[0].elements[0].distance.text;
                    this.nearbyCustomers[x].duration = response.rows[0].elements[0].duration.text;
            });

Om den andra frågan kommer jag att kolla den senare och redigera svaret

Svar #2

Tack för era svar. NgZone hjälpte med problemet med att förändringsdetektering låg efter. Och för den andra delen av min fråga, här är hur jag löste det (Inte säker på om detta är den bästa lösningen men fungerar bra för mig)

Jag har filtrerat kunderna och bara tilldelat värden förutom den valda på detta sätt: this.nearbyCustomers=this.customers.filter(c => c.id != this.selectedDeliveryDestinationId);. På detta sätt behövde jag bara loopa igenom arrayen av nearbyCustomers och utesluta ursprunget - vilket sparade ett onödigt API-anrop i varje loop :-)

findNearbyCustomers() {
        this.isFindButtonClicked = true;
        this.nearbyCustomers = this.customers.filter(c => c.id != this.selectedDeliveryDestinationId);
        var origin = this.customers.find(c => c.id == this.selectedDeliveryDestinationId);
        var originLatLng = origin.latitude.toString()+","+origin.longitude.toString();
        var service = new google.maps.DistanceMatrixService();
        for (let x = 0; x < this.nearbyCustomers.length; x++) {
            var destinationLatLng = this.nearbyCustomers[x].latitude.toString()+","+this.nearbyCustomers[x].longitude.toString();        
            service.getDistanceMatrix({
                origins: [originLatLng],
                destinations: [destinationLatLng],
                travelMode: google.maps.TravelMode.DRIVING
            }, (response, status) => {
                if (status.toString() == 'OK') {
                    this._ngZone.run(() => {
                        this.nearbyCustomers[x].distance = response.rows[0].elements[0].distance.text;
                        this.nearbyCustomers[x].duration = response.rows[0].elements[0].duration.text;
                    })
                }
            })
        }
    }