Dealing with delays in rendering certain values with Angular interpolation & ways to eliminate an element from an array of TypeScript objects

I am currently developing a web application using ASP.NET Core - Angular. The app allows users to select a customer as the starting point and then calculates the distance & duration to other customers using Google Maps Distance Matrix Service. Although I am able to retrieve the values successfully (based on my console log), there is a lag when rendering the distance & duration values in the template using angular interpolation. Additionally, the table containing this information is only displayed after clicking a button, triggered by setting isFindButtonClicked to true.

  1. Can someone assist me in identifying and resolving this issue?

https://i.sstatic.net/RbxAA.png

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 function for calculating distance/duration:

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);
                }
            })
    }
}

Snippet from the angular template:

<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. In a previous attempt, I used an if statement
    if (this.customers[x].id != this.selectedDeliveryDestinationId)
    to exclude the selected customer (origin) from the calculations. However, when trying to assign a value to object property and render it, I encountered a
    Cannot set property 'distance' of undefined
    error, which suggests index manipulation issues. What would be the best approach to exclude one item from the array effectively? Alternatively, is it possible to hide a specific row in the HTML instead?

Thank you.

Answer №1

To efficiently update your table in this specific scenario, utilizing ngZone is necessary.

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

Within the constructor, ensure to include: private _ngZone: NgZone. Then, upon successful retrieval of distance matrix data:

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;
            });

I will address the second inquiry later and make necessary updates to the answer.

Answer №2

Appreciate your input and suggestions on this matter. Utilizing NgZone has proven to be instrumental in addressing the issue of lagging change detection. As for the second part of my inquiry, I approached it by implementing a solution that may not be deemed as optimal, but it fulfills my requirements effectively.

To tackle the task of filtering customers and excluding the selected one, I resorted to the following code snippet:

this.nearbyCustomers = this.customers.filter(c => c.id != this.selectedDeliveryDestinationId);
. This method enabled me to streamline the process by iterating through the array of nearbyCustomers while omitting the origin, thereby eliminating unnecessary API calls within each 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;
                    })
                }
            })
        }
    }

Answer №3

One way to enhance your search functionality is by implementing a Pipe to filter the nearbyCustomers that are currently selected.

<tbody>
    <tr *ngFor="let nearbyCustomer of nearbyCustomers | nearbyCustomerFilter">
        <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>

Develop a Service that supplies information about the currently selected nearbyCustomer to the Pipe.

By updating your List whenever a different customer is chosen, the Pipe will automatically remove the corresponding entry from the view.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Possible Inconsistencies with the LookAt Feature in Three.js

Attempting to use the lookAt function to make zombies move towards the character has been a challenge. The problem lies in the fact that they are not turning correctly but at odd angles. Here is the code snippet I tried: var pos = new THREE.Vector3(self ...

Tips for ensuring the alignment of a table header and body once data has been loaded into it

I am currently developing an Angular 7 application where I am trying to populate a table with data retrieved from a web service. However, the issue I am facing is that the headers of the table do not align properly with the body content after loading data ...

There was an issue encountered while trying to install Electron using the command 'npm install electron'

While attempting to install electron using npm install electron, I encountered the following error: 908 error code 1 909 error path C:\Users\name\Documents\name\Code\code\node_modules\gl 910 error command failed ... ...

Creating a unique theme export from a custom UI library with Material-UI

Currently, I am in the process of developing a unique UI library at my workplace which utilizes Material-UI. This UI library features a custom theme where I have integrated custom company colors into the palette object. While these custom colors work perfe ...

The correct way to add to a string array that has been passed as props to a functional component

There is a parent component that establishes a useState hook with a string array. Then, there is a child component tasked with updating the string array. To accomplish this, both the string array and the useState function are passed to the child component. ...

Reached the maximum number of iterations for Angular 10 $digest() function

Currently, I am following a MEAN stack tutorial on Thinkster and encountering an issue with my Angular factory service. Angular.js:11598 Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting! Watchers fired in the last 5 iterations: [] H ...

Tips for efficiently waiting for the outcome in a unified function for multiple callbacks within node.js

Perhaps the question title is not the most appropriate, but let me explain what I am trying to achieve in my code // First Callback Function connection_db.query(get_measure_query,function(err,user_data1){ if(err){ // throw err; ...

When utilizing custom modules in Node.js, is it more effective to require the module from within a function or at the top of the script?

I have developed a custom script that includes all of my common settings and functions. One specific function within this script takes a timestamp as input and outputs a human-readable date with a customized format using Moment.js. The custom script is st ...

Combine two sets of JavaScript objects based on their positions using Underscore.js

Data Set 1: {id: "01", name: "John Doe", age: "25", city: "New York", country: "USA"} Data Set 2: [{key:'id', value:'01'},{key:'name', value:'John Doe'},{key:'age', value:'25'},{key:'city& ...

`When the component is loaded, subscribing to the event will work properly.`

I am facing challenges with handling data retrieved from a Database. I want to send it to a central service so that I can utilize it later when loading the components that require this data. The issue I'm encountering is that the central service appea ...

Which JavaScript library or template engine would be most suitable for this scenario?

I am tasked with creating an invite your Facebook friends module that will display the names and photos of your friends, allowing you to message them. It is essential that this feature seamlessly integrates into my website's design, so I need to style ...

What do you want to know about Angular JS $http request?

My goal is to send a request using $http with angular js in order to retrieve a json object from google maps. $http.get('http://maps.googleapis.com/maps/api/geocode/json?address=' + data[ 'street' ] + ',' + data[ 'city&a ...

transferring information from a JavaScript variable to an EJS variable

I am currently storing a value in the 'items' variable within a script tag in an HTML document. However, I now need to pass this data from 'items' to the back end in order to store it in a database. I attempted to make 'selectedTea ...

Accordion symbol for adding or subtracting

Looking for a way to change the Toggle text in my angular 7 application accordion to images or content displaying a + sign for collapse and - for expand. I need to achieve this using CSS in my SCSS stylesheet so that I can later change the color of the sig ...

Unable to assign attribute following discovery

Can the attribute of an anchor element that is found using find() be set? I attempted this: $(this).children('a').setAttribute("href","a link"); Although it does locate the anchor element, why am I receiving an error when trying to use setAttr ...

Learn how to utilize the "is" status in Postma within your code, even when this particular status is not included in the response

Service.ts Upon invoking this function, I receive a JSON response similar to the following: public signupuser(user: Users): Observable<boolean> { let headers = new Headers(); headers.append('Content-Type', 'application/json&a ...

Arrays Filtering without Containing Elements

Is there a utility function in Knockout to filter one array based on another array, or will I need to use JavaScript? First : var obj1 = [{ "visible": "true", "id": 1 }, { "visible": "true", "id": 2 }, { "visible": "true", "id": ...

Conceal Element in React if it is the Final Item

Is there a way to hide the TimelineConnector if it is on the last item? I am looking for some guidance on how to achieve this. Please take a look at my codesandbox below: CLICK HERE {timelines.lastIndexOf(index) !== 1 ? <TimelineConnector /> : &quo ...

javascript accessing all data in firebase real-time database using JavaScript the right way

Working with node.js, I am retrieving data from the firebase real-time database. However, the data is being returned in the following format: Data Retrieval Code import firebaseApp from '../config.js'; import { getDatabase, ref, onValue } from & ...

Exploring the world of functional programming in Java can be a rewarding experience, especially

I am seeking a method to define generic computation on a data set and have the compiler alert me if there are any errors. Having experience with TypeScript, I have seen that you can achieve something like this: /** * Type inferred as: * Array<{ * ...