How does the order of objects in an array change when using *ngFor in Angular with a .subscribe() method in Ionic 3?

As a newcomer to Ionic 3 & Angular, I encountered a challenge with the *ngFor and .subscribe() method. Please bear with me if this question seems simple. I attempted to understand the behavior of the http.get(..).map(..).subscribe() function when combined with *ngFor to manage an array of objects and display the records to the user using *ngFor in the .html template file, but I am struggling to comprehend *ngFor's peculiar behavior.

In my Ionic 3 App, I fetch data from an API and store it in a component variable named "users," which is defined as follows in the component .ts file -

users: Array<any>;;

I have the following component function that populates the users array with data -

addUser(count: number) {
  this.http.get('https://randomuser.me/api/?results=' + count)
  .map(data => data.json().results)
  .subscribe(result => {
    for (let val of result) {
      this.users.push(val);
    }
  })
}

Initially, I retrieve data for 10 users from the API using the above component function by simply calling it within my ngAfterViewInit() function like -

this.addUser(10); 

This provides me with 10 user record objects in my "users" array, which I display to the user in the .html file as follows -

<ion-card *ngFor="let user of users">
  {{user.email}}
</ion-card>

At this point, *ngFor places the last array element first in the view and renders the records in descending order, starting from index 9 to 0 (LIFO order).

Subsequently, I remove the last element from the users array using users.pop(); and add another element at the beginning at index 0 by shifting the current elements using users.unshift(..) in the following function called addNewUser(1); -

addNewUser(count: number) {
      this.http.get('https://randomuser.me/api/?results=' + count)
      .map(data => data.json().results)
      .subscribe(result => {
        for (let val of result) {
          this.users.unshift(val);
        }
      })
    }

At this moment, considering the initial array with 10 elements, the last object at index 9 has been removed and another element at index 0 has been added, causing the previous elements at indexes 0-8 to shift to indexes 1-9.

Upon doing this, my view updates due to *ngFor, and surprisingly this time it shows the recently inserted element first from the array of objects, which contradicts the previous order followed by *ngFor in rendering elements on the screen.

Why does *ngFor in Ionic 3 display the recently added object element first from the array of objects, which is dependent on the .subscribe() method. I am genuinely puzzled by this.

I truly need clarification on *ngFor and subscribe(). Kindly assist me.

Note: The API mentioned above is publicly accessible for testing, and you may call it to check the response structure. A sample API response is provided below on calling https://randomuser.me/api/?results=1 -

{
    "results": [
        {
            "gender": "male",
            "name": {
                "title": "mr",
                "first": "daniel",
                "last": "stoll"
            },
            "location": {
                "street": "9719 tannenweg",
                "city": "cottbus/chosebuz",
                "state": "bremen",
                "postcode": 81443
            },
            "email": "example@email.com",
            "login": {
                "username": "greenleopard994",
                "password": "chat",
                "salt": "OUjisBdQ",
                "md5": "8148d51998f3fef835a5f3979218c181",
                "sha1": "131ae09d045b345efe36a330bf17a450b76f7de3",
                "sha256": "94c3a362b5f516d0fb1d4e9dbb632d32d57b8886d5cc7bf0d5cedc99e7d55219"
            },
            "dob": "1957-04-26 22:07:14",
            "registered": "2002-04-29 10:57:34",
            "phone": "0556-4348870",
            "cell": "0172-5116200",
            "id": {
                "name": "",
                "value": null
            },
            "picture": {
                "large": "https://randomuser.me/api/portraits/men/14.jpg",
                "medium": "https://randomuser.me/api/portraits/med/men/14.jpg",
                "thumbnail": "https://randomuser.me/api/portraits/thumb/men/14.jpg"
            },
            "nat": "DE"
        }
    ],
    "info": {
        "seed": "8fd4afe85884c767",
        "results": 1,
        "page": 1,
        "version": "1.1"
    }
}

Refer to this example showing my issue: Example Link

Answer №1

In case you encounter a problem with sorting and indexing that seems connected, one solution is to deal with the problem by providing an index:

*ngFor="let person of people; let i = index"

After that, you can refer to the specific index value directly:

people[i]

Answer №2

To ensure proper functionality, it is recommended to duplicate the array before making any changes. Modifying array elements during a loop may result in undesirable outcomes.

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

Sharing data across multiple components while navigating in Angular is a common requirement. By passing

I have a specific structure set up in my application: <div class="container"> <top-navbar></top-navbar> <router-outlet></router-outlet> <navbar></navbar> </div> The components I have include Top ...

The challenge of distinguishing between array values and their corresponding positions

Imagine we have the code snippet below: def execute(input) start = 0 cycle = 0 while true opcode = input[start] input1 = input[start + 1] input2 = input[start + 2] output = input[start + 3] if opcode == 1 input[output] = i ...

Adjust the color of the text in Ionic based on the condition

My current solution involves highlighting text in a small slider after a user tap, but it feels very makeshift. <ion-slide *ngFor="let loopValue of values"> <div *ngIf="viewValue == loopValue"> <b> {{loopValue}} </b> ...

The additional parameters I am trying to append are being overwritten by the set parameters in the httpInterceptor

Issue Description: I have implemented an HttpInterceptor that adds an id and token to all requests when the user's credentials are available. However, I am facing the problem of the interceptor overwriting any additional HttpParams added to a request. ...

Learning the implementation of uib-tabset in Angular 2 with ng-bootstrap

Currently, I am working on an angular2 project and I am curious to know if there is a way to utilize uib-tabset in angular2. In the past, when I was using angularjs, I could easily use ng-bootstrap. This allowed me to incorporate <uib-tabset></u ...

Uh-oh! Angular 6 has encountered an unexpected error with template parsing

I am currently working on an Angular application where I have integrated the FormsModule from '@angular/forms' in my app.module.ts. However, despite this, I keep encountering the error message No provider for ControlContainer. Error log: Uncaug ...

Creating a blank webpage after including a component tag for an Angular form

I encountered an issue while developing an Angular form. It seems that using the app-name-editor tag causes my entire HTML page to go blank, and the form does not display. However, removing the tag restores the webpage's functionality. This leads me t ...

typescript when an argument is missing, it will automatically be assigned

Here is my TypeScript function: function more(argv: {a: number, b?: string}): number{ console.log( b) return a } I am invoking the function this way: let arc = more({a: 5}) Unexpectedly, I see 10 in the console. I was anticipating undefined ...

"Encountered an error in Angular: ContentChild not found

Working with Angular 5, I am attempting to develop a dynamic component. One of the components is a simple directive named MyColumnDef (with the selector [myColumnDef]). It is used in the following: parent.compontent.html: <div> <my-table> ...

Angular module structure, is it appropriate to utilize shared components within the module?

I have been deliberating on the correct approach for designing my Angular project. The main entity in this application is an Order. An Order can be used in three different ways: Distribution Assigning Execution My decision was to create three modules: ...

Unit testing Angular components can often uncover errors that would otherwise go unnoticed in production. One common

I need assistance writing a simple test in Angular using Shallow render. In my HTML template, I am utilizing the Async pipe to display an observable. However, I keep encountering the following error: Error: InvalidPipeArgument: '() => this.referenc ...

Error shown in console when using Angular 7 FormControlName

My webpage has a reactive form, but I keep encountering an error message that states: ERROR Error: formControlName must be used with a parent formGroup directive. Make sure to include a formGroup directive and pass it an existing FormGroup instance (you ...

Arrange objects in an array according to the order specified in another array

Here is my array of car makes: const makes = [ {id: "4", name: "Audi"}, {id: "5", name: "Bmw"}, {id: "6", name: "Porsche"}, {id: "31", name: "Seat"}, {id: "32", name: "Skoda"}, {id: "36", name: "Toyota"}, {id: "38", name: "Volkswagen"} ] Now, I want to o ...

Display alternative navigation paths to the user in Angular that differ from the original routes

I am currently developing a full stack web application using Angular, Node (Express), and mySQL. I am looking to display a different route to the user than the actual one. Is there a way to achieve this? For instance, let's say this is my dashboard pa ...

How to Nest Interfaces in TypeScript

I'm just starting to learn about Angular and I am having trouble getting the interface class to work properly. export interface Header { parentTitles: string; childHeaders: ChildHeader[]; titleIcon: string; url: string; } export interf ...

The Vue application is refusing to compile due to a syntax error caused by the presence of 'return' outside of a function

Upon attempting to run a build on my Vue app, I encountered the following syntax error. error in ./src/pages/Calendar.vue?vue&type=script&lang=ts& Syntax Error: 'return' outside of function. (175:4) 173 | getEventColor(event, Even ...

What is the best way to set a variable as true within a pipeline?

Could someone assist me with a coding issue I'm facing? If the id is null, I need variable x to be true. I am unable to use if and else statements within the pipe. Any guidance would be greatly appreciated. private x = false; private y = false; n ...

Creating a JAR file for an Angular 2 application with Maven

My Front-End application is constructed using Angular2 + Webpack, organized as follows: > app > config > dist > dll > node_modules > src pom.xml package.json ... (other files) Currently, I am exploring th ...

Using typescript in react to define conditional prop types

Currently, I am utilizing react-select as my select component with the multi prop. However, my goal is to have the onChange argument set as an array of options when the multi prop is true, and as OptionType when false. To achieve this, I am implementing di ...

How to retrieve the length of an array stored in the data object of a Vue instance

Having trouble retrieving the length of an array in vue. The array is located in the data object like so: data() { return { slides: [ { image: require("@/assets/img/carousel/couple.jpg"), caption: "A coupl ...