The array is not being spliced in the DOM, however, it is being spliced in the console - Ionic 2+/Angular

My scenario involves a dynamic array filled with items and values. The goal is to remove an item from the view list when a user clicks a button on that particular item. I'm struggling to identify why this functionality isn't working as expected. Could it be due to how the data is structured? Despite seeing it being removed in the console, the issue persists. Any insights would be greatly appreciated. Thank you!

TS:

export class Page{
    items: Item[];

    constructor(public alertCtrl: AlertController){}

    removeitem(i) {
        let confirm = this.alertCtrl.create({
            title: 'Confirm',
            message: "text.",
            buttons: [
                {
                    text: 'Cancel',
                    handler: () => {
                        console.log('Disagree clicked');
                    }
                },
                {
                    text: 'Save',
                    handler: () => { 
                        this.presentToast() 
                        this.items.splice(i, 1);

                    }
                }
            ]
        });
        confirm.present();
    }

getItems(){
   this.stopService.getItems().subscribe(item => { 
     this.items = item 
  })

  }


}

HTML:

<div *ngFor="let item of items; index as i ">
    <h3>{{item.description}}</h3>
    <button item-end ion-button full (click)="removeitem(i)">remove item</button>
</div>

EDIT

Here's how I retrieve items using a service --

getItems(): Observable<any> {
         return this.http.get(someEndpoint)
        .map(res => res.json());
    }

Answer №1

Follow these steps:

removeitem(i) {
        let confirm = this.alertCtrl.create({
            title: 'Confirm',
            message: "text.",
            buttons: [
                {
                    text: 'Cancel',
                    handler: () => {
                        console.log('Disagree clicked');
                    }
                },
                {
                    text: 'Save',
                    handler: () => { 
                        this.presentToast() 
                        this.items = [...this.items.filter((item, index) => index !== i];
                    }
                }
            ]
        });
        confirm.present();
    }

This will completely modify the object reference and trigger a DOM update.

If the above approach doesn't work, try putting your splice inside a setTimeout function:

setTimeout(() => { this.items.splice(i, 1); }, 0);

You can also include public zone: NgZone in the constructor and execute splice within

this.zone.run(() => { this.items.splice(i, 1); });
. This method helps with change detection.

UPDATE:

In your getItems() method, consider the following code:

    getItems() {
       this.stopService.getItems().subscribe(item => { 
         this.items = [...item];
      });
   }

For more information, check out this Plunker demo:

Plunker demonstration

Answer №2

It appears that the Angular change detector was not triggered automatically. You can manually initiate it by following these steps:

import { ChangeDetectorRef } from '@angular/core';
constructor(private changeDetectorRef: ChangeDetectorRef) {

}
removeItem(i) {
        let confirm = this.alertCtrl.create({
            title: 'Confirm',
            message: "text.",
            buttons: [
                {
                    text: 'Cancel',
                    handler: () => {
                        console.log('Disagree clicked');
                    }
                },
                {
                    text: 'Save',
                    handler: () => { 
                        this.presentToast();
                        this.items.splice(i, 1);
                        this.changeDetectorRef.detectChanges(); // Manually triggering the Angular change detector
                    }
                }
            ]
        });
        confirm.present();
    }

Answer №3

Take out the line let items = and add the following code below:

getItems(): Observable<any> {
         return this.http.get(someEndpoint)
        .map(res => res.json());
    }

For further information, refer to this link: Troubleshooting error message "Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays"

Answer №4

According to @robbannn, angular fails to detect the change, therefore modify

this.products.splice(i, 1);

In order to

this.product = this.products.splice(i, 1).slice()

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

Set up Angular library by downloading from a specified local or network location

If I were to create an Angular library using the following commands: ng new libraries-workspace --create-application=false cd libraries-workspace ng generate library test-library After creating and building the library using the command below: ng build te ...

How can the count of specific values matching total records be determined in Angular/TypeScript using JSON?

In the dataset provided below, how can we determine the count of applicable impacts, non-applicable impacts, and FYI impacts for nested records under the assigned_to key instead of the parent record? The expected results should be: For 1st Record Appl ...

Challenges encountered when assigning values in a form with Material UI, Formik, and Typescript

When attempting to set the 'role' and 'active' values on a form, I encountered a couple of issues. The first problem arises from the fact that the selectors' original values are not being properly set. These values are fetched in ...

Setting a default value for a textfield within Angular 4

Within my for loop, I am displaying the name and price of a selected product. Users can input a quantity, with the default being 1. How can I set the text field value to default to 1? I've attempted the following method but it doesn't seem to be ...

How to capture and log request and response data when using the HttpService in NestJS?

Is there a way to log requests, responses, and errors using the HttpService within the HttpModule? In the past, I have used Interceptors with AXIOS. While HttpService wraps axios, I'm having trouble adding interceptors. There doesn't seem to be ...

How can I achieve this using JavaScript?

I am attempting to create a TypeScript script that will produce the following JavaScript output. This script is intended for a NodeJS server that operates with controllers imported during initialization. (Desired JavaScript output) How can I achieve this? ...

Utilizing objects as values with `react-hook-form`

About the Issue I'm facing an issue with a component that utilizes an object as its value. My goal is to integrate this component with react-hook-form The challenge arises when react-hook-form considers my object as a nested form control Background ...

Angular2: Maintaining a continuous connection for a child component to receive input from the parent component post onInit

I'm currently working on integrating an error message component into another parent component. The child component, which displays the error message, has an input attribute that the parent component uses to pass the error message. However, I've e ...

Having trouble with Angular 2 and Ionic2 mocks? Getting an error message that says "No provider

Currently in the process of creating a spec.ts file for my application. The challenge I'm facing is related to using the LoadingController from ionic-angular. In order to configure the module, it requires providing the LoadingController (due to its pr ...

Steps to automatically set the database value as the default option in a dropdown menu

I'm in need of assistance with a project that I'm working on. To be completely honest, I am struggling to complete it without some help. Since I am new to Angular and Springboot with only basic knowledge, I have hit a roadblock and can't mak ...

Access-Control-Allow-Methods does not allow the use of Method PUT in the preflight response, as stated by Firebase Cloud Functions

I am facing an issue with my Firebase cloud function endpoint. I have a setup where it forwards PUT requests to another API endpoint. I have configured the following Access-Control-Allow- headers: // src/middlewares/enableCORS.ts export default function en ...

Changing a d3 event from JavaScript to Typescript in an Angular2 environment

I am a beginner in Typescript and Angular 2. My goal is to create an Angular2 component that incorporates a d3js tool click here. However, I am facing challenges when it comes to converting it to Typescript. For instance, I am unsure if this code rewrite ...

Having trouble utilizing the ng-Command in Angular?

Currently, I am attempting to set up Angular in a vagrant-box environment. npm install -g @angular/cli Unfortunately, I encounter an error while trying to use the client: The program 'ng' is currently not installed. You can install it by typin ...

What is the best way to retrieve the previous URL in Angular after the current URL has been refreshed or changed

Imagine being on the current URL of http://localhost:4200/#/transactions/overview/5?tab=2 and then navigating to http://localhost:4200/#/deals/detail/ If I refresh the deals/detail page, I want to return to the previous URL which could be something like h ...

Issue: Unable to determine all parameters for FirebaseDataService

I've been working on abstracting and concealing the implementation of my DataService through the setup below: DataService: import { Observable } from 'rxjs/Observable'; export abstract class DataService { abstract getMyData(): Observa ...

Limiting the assignment of type solely based on its own type, without considering the components of the type

I have defined two distinct types: type FooId = string type BarId = string These types are used to indicate the specific type of string expected in various scenarios. Despite TypeScript's flexibility, it is still possible to perform these assignment ...

The NGX countdown timer is experiencing a discrepancy when the 'leftTime' parameter exceeds 24 hours, causing it to not count down accurately

When the leftTime configuration exceeds 864000, the timer does not start from a value greater than 24 hours. <countdown [config]="{leftTime: `864000`}"></countdown> For example: 1. When leftTime is set to `864000`, the Timer counts down from ...

Typesafe-actions for defining typings of async actions reducers

I'm currently facing a minor issue while using createAsyncAction from the library typesafe-actions (Typesafe Actions) and correctly typing them for my reducer function Below is an example of the action being created: export const login = createAsync ...

angular 6 httpclient include login information in the URL

When attempting to make a HTTP GET request from an Angular 6 project to a CouchDB, I encountered a 401 Error "You are not authorized to access this db." despite passing the credentials in the URL. Below is the code snippet: var url = "http://user:passwor ...

Linking a variable in typescript to a translation service

I am attempting to bind a TypeScript variable to the translate service in a similar way as binding in HTML markup, which is functioning correctly. Here's what I have attempted so far: ngOnInit() { this.customTranslateService.get("mainLayout.user ...