Surprising Logging Quirks in Angular

I've encountered a perplexing issue in my Angular app where an array is logged before adding an element to it, yet the log shows the updated array with the added element. This array is then utilized in an HTML file with ngFor.

component.ts file

interface OrderItem {
  quantity: number | null,
  product: any
}

export class Component{

orderItems: OrderItem[] = [{ quantity: null, product: {} }]

addProduct(): void {
    console.log(this.orderItems);
    this.orderItems.push({ quantity: null, product: {} })
  }

}

html file

<mat-form-field>
        <ng-container *ngFor="let ele of orderItems">
          <mat-form-field>
            <mat-label>Product</mat-label>
            <mat-select [(ngModel)]="ele.product">
                <mat-option *ngFor="let e of productlist" [value]="e._id" >{{e.productName}}</mat-option>
            </mat-select>
          </mat-form-field>
        
        <mat-form-field>
          <mat-label>Number of Items</mat-label>
          <input matInput type="number" [(ngModel)]="ele.quantity" placeholder="Enter the number of items">
        </mat-form-field>
        <br>
        </ng-container>
      <button mat-icon-button (click)="addProduct()">
        <mat-icon>add</mat-icon>
      </button>

</mat-form-field>

The output in the console is quite peculiar :

[{…}]

This results in an array with two objects :

[{ quantity: null, product: {} },{ quantity: null, product: {} }]

Answer №1

Explanation of the provided code:

interface OrderItem {
  quantity: number | null,
  product: any
}

export class Component{
// property 'orderItems' is defined with a value of '[{ quantity: null, product: {} }]'
orderItems: OrderItem[] = [{ quantity: null, product: {} }]

addProduct(): void {
    // Logging the current 'orderItems' array before pushing a new item.
    console.log(this.orderItems);
    this.orderItems.push({ quantity: null, product: {} })
  }

}

The expected output matches what was logged. To get a better idea, you can use JSON.stringify to convert the object into a formatted string.

//  prints the formatted string representation of 'orderItems'
console.log(JSON.stringify(this.orderItems, null, 4)); 

The output from console.log can be interpreted as an array [] containing a single object {} with two properties - quantity and product!

Here is a live example where only one object is logged:

Check out the stackblitz demo

Answer №2

When you log an object or array to the console, what you see is a dynamic representation directly connected to its actual memory reference. Any changes made to the object will be instantly reflected in the displayed output. When using the push method to modify an array, you are essentially altering it in place.

In the code snippet, when the console.log function is called on the orderItems array, it only contains one element at that moment. However, immediately after, another item is added which updates the logged content to show both elements.

It is generally recommended to avoid direct mutations. Instead of modifying the existing array by pushing new items into it, consider creating a fresh array with the additional item included along with all previous ones. By doing this, comparing the console outputs before and after the assignment will reflect the expected outcome:

console.log(this.orderItems); // [{ quantity: null, product: {} }]
this.orderItems = [...this.orderItems, { quantity: null, product: {} }];
console.log(this.orderItems); // [{ quantity: null, product: {} }, { quantity: null, product: {} }]

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

Encountering difficulty in presenting detailed information using a .json file

My photo gallery app functions perfectly when fetching data from jsonplaceholder.typicode.com. However, when I use my own local data, it breaks whenever I try to click on a photo to view its details. How is it possible for the photos to display correctly b ...

The universe's cosmic energy is unable to retrieve uploaded documents

Struggling for days now with the issue of not being able to run any real tests using Karma. I can run basic sanity tests that don't require imports, but as soon as I try to import something from my app, I encounter this error: system.src.js:1085 GE ...

Using Angular 10 to make an HTTP POST request, with the goal of appending a string

Whenever I try to send a post request to an api endpoint, I keep encountering an error with status code 500. name: "HttpErrorResponse" ok: false status: 500 statusText: "Internal Server Error" Below is the code I am using: var selected ...

Error encountered when asynchronously iterating over an object in TypeScript

Could someone please help me understand why I am getting an error with this code? var promise = new Promise((resolve, reject) => { resolve([1, 2, 3, 4, 5]); }); async function doSomethingAsync() { var data = await promise; data.forEach(v = ...

Leveraging the async pipe within the ngOnInit lifecycle hook

In my angular application, I have several API calls where I need to display a loading component while waiting for server data. To achieve this, I've implemented a loader service as shown below: import { Injectable } from '@angular/core'; im ...

Navigating through template files in Angular 2 components

Currently, I am working on developing a top-level component that requires an input of type @Input(): Object. This object needs to contain an array of components, which will be iterated through using *ngFor, and the templates of these components must be p ...

Sending an event from a child component to another using parent component in Angular

My form consists of two parts: a fixed part with the Save Button and a modular part on top without a submit button. I have my own save button for performing multiple tasks before submitting the form, including emitting an Event to inform another component ...

Typescript validation for redundant property checks

Why am I encountering an error under the 'name' interface with an excess property when using an object literal? There is no error in the case of a class, why is this happening? export interface Analyzer { run(matches: MatchData[]): string; } ...

How can I transfer user input to a service method in Angular?

My goal is to capture user input and pass that value into a service method to retrieve data related to the input and present it. (The getApplicantById method fetches data from the database in Postman.) Here's the code I've been working on: compon ...

Typescript or Angular 2 for Google Maps

Is there a way to integrate Google Maps Javascript API with Typescript or Angular 2? Although libraries like https://github.com/SebastianM/angular2-google-maps are available, they may not provide full support for features like Events and Places Libraries ...

How to minimize xAxes labels in Chart.js

As a newcomer to Chart.js, I am encountering some challenges. My goal is to create a bar chart that displays hourly information. However, when attempting to show data for a week, a month, or an extended period, I face issues with reducing the labels on the ...

Using Typescript: Defining a property's type based on the value of another property in the same object

I'm dealing with a TypeScript interface that consists of two properties (type:string and args:object). The contents of the args property may vary based on the value of the type. I'm looking for the correct type definition to specify for the args ...

When using TypeScript, how can I effectively utilize the Component property obtained from connect()?

Software Development Environment TypeScript 2.8 React 16 Redux Foo.tsx interface IFooProps{ userId:number } class Foo extends Component<IFooProps>{ render(){ return <p>foo...</p> } } const mapStateToProps = (state: I ...

'Error: The type is missing the 'previous' property - Combining TypeScript with ReactJS'

I am quite new to using reactjs and ts. While I understand the error that is occurring, I am unsure of the best solution to fix it. Currently working with reactjs, I have created an: interface interface IPropertyTax { annul: { current: number; p ...

Tips for simulating a Ref

I have a Vue3 component where, within the setup(), I have defined the following function: const writeNote(note: Ref<Note>) => { console.log(`note ${note.id}`) } This function takes a Ref<Note>, with Note being an Interface. There are two s ...

Issue with using useState inside alert: unexpected empty array

I am facing an issue with the 'exercises' useState in my code. The useEffect function correctly prints the 'exercises' after every change, but when I press the 'Finish' button, the 'exercises' suddenly become empty. ...

Error encountered in Angular testing when component fixture becomes undefined after test execution with subcomponents in version 4.0.0-beta.8

I'm facing a strange issue while testing my Angular code. Setting things up goes smoothly, but when I define subcomponents in the TestBed.configureTestingModule declaration, things start to break. The initial test within a describe block works fine, b ...

Leveraging Expose in combination with class-transformer

I have a simple objective in mind: I need to convert the name of one property on my response DTO. refund-order.response.dto.ts export class RefundOrderResponseDto { @Expose({ name: 'order_reference' }) orderReference: string; } What I w ...

The user interface in Angular 7 does not reflect the updated values after subscribing

Upon examining the code provided, it is evident that the UI does not reflect the updated value even though the field is set correctly. I have attempted two different approaches but have not explored the change detection approach as I believe the current c ...

Rect cannot be resized using mouse events

I am currently working on resizing the rectangle inside the SVG using mouse events. To achieve this, I have created another circle shape at the right bottom edge of the rectangle and implemented resize events on that shape. However, I'm facing an issu ...