In Angular, any newly added item is not deletable until the page is refreshed

I am currently developing a project in Angular 12 and utilizing JSON-server to store the data. The CRUD operations are functioning as expected.

However, I have encountered an issue where after adding a new item through the form, the delete and update buttons do not work unless I refresh the page.

Upon clicking the delete button without refreshing, this is the error displayed in the console.

product.service.ts

  url = environment.url + 'products/';
  constructor(private http: HttpClient) {}

  getListProduct() {
    return this.http.get<Product[]>(this.url);
  }

  addProduct(product: Product) {
    return this.http.post(this.url, product);
  }

  deleteProduct(id: string) {
    return this.http.delete(this.url + id);
  }
  updateProduct(product: Product) {
    return this.http.put(this.url + product.id, product);
  }
}

main-product.component.ts

export class MainProductComponent implements OnInit {
 inputProduct: Product = new Product();
 isForm: Boolean = false;
 buttonString: String = 'Add New Product';
 listProduct: Product[] = [];

 constructor(private productService: ProductService) {}

 ngOnInit(): void {
   this.productService
     .getListProduct()
     .subscribe((data: Product[]) => (this.listProduct = data));
 }
 changePage() {
   this.isForm = !this.isForm;
   if (this.isForm) {
     this.buttonString = 'Go Back To List';
   } else {
     this.inputProduct = new Product();
     this.buttonString = 'Add New Product';
   }
 }
 deleteProduct(p: Product) {
   let i = this.listProduct.indexOf(p);
   this.productService
     .deleteProduct(p.id)
     .subscribe(() => this.listProduct.splice(i, 1));
 }
 saveProduct(product: Product) {
   let i = this.listProduct.indexOf(product);
   if (i != -1) {
     //update a product
     this.productService
       .updateProduct(product)
       .subscribe(() => (this.listProduct[i] = product));
   } else {
     //add a new product
     this.productService.addProduct(product).subscribe(
       () => this.listProduct.push(product),
       () => console.log('error')
     );
   }
   this.isForm = false;
   this.buttonString = 'Add New Product';
   this.inputProduct = new Product();
 }

 updateProduct(p: Product) {
   this.isForm = true;
   this.inputProduct = p;
 }

form-product.component.ts

export class FormProductComponent implements OnInit {
  selectedFile = null;
  private product!: Product;
  productForm!: FormGroup;
  @Input() updateProduct!: Product;
  @Output() addEvent = new EventEmitter<Product>();
  constructor(private builder: FormBuilder) {}

  ngOnInit(): void {
    if (this.updateProduct === null) {
      this.product = new Product();
    } else {
      this.product = this.updateProduct;
    }

    this.productForm = this.builder.group({
      title: [
        this.product.libelle,
        [Validators.required, Validators.minLength(3)],
      ],
      price: [
        this.product.prixUnitaire,
        [Validators.required, Validators.min(10)],
      ],
      photo: [this.product.photo, Validators.required],
      category: [this.product.categorie, Validators.required],
    });
  }
  upload(event: any) {
    this.selectedFile = event.target.files[0].name;
    console.log(this.selectedFile);
  }
  addProduct() {
    this.product.libelle = this.productForm.value.title;
    this.product.prixUnitaire = this.productForm.value.price;
    this.product.photo = String(this.selectedFile);
    this.product.categorie = this.productForm.value.category;

    this.addEvent.emit(this.product);
  }
}

Answer №1

It seems like there may be an issue with saving the response from the create method in your array on the front end.

The corrected code should look something like this:

// add a new product
     this.productService.addProduct(product).subscribe(
       newProduct => this.listProduct.push(newProduct),
       () => console.log('error')
     );

This response was written quickly on a phone, for a more detailed explanation:

I don't have experience with json-server, so I'm unfamiliar with it. Based on their documentation, they seem to create an id for the object before sending it to the server. If you're not generating an id for your objects, it might be causing the issue.

In general, the front-end creates an object without an id, sends it to the backend where it gets stored with a generated id. The backend then returns the object with the id, allowing further actions to be performed on it using the id (get, put, delete, etc).

Your current code is pushing the object sent to the backend into the array instead of the object returned by the backend, which would typically have an id.

If json-server requires ids to be created and assigned, you'll need to update your product class to handle that assignment when creating new objects.

The error you're seeing is likely due to the id property being undefined on the object retrieved from the array, rather than it not being found at all.

In a standard scenario, the id would come from the backend, but since you're not adding the returned object to the array, it's missing. If json-server mandates passing ids, then updating your front end to generate the id should resolve the issue.

Answer №2

peinearydevelopment has provided a useful insight. It's recommended to refetch the list after adding or deleting items, especially if you need to perform calculations, queries, or apply server-side ordering.

For example:

constructor(private productService: ProductService) {}

 ngOnInit(): void {
   this.fetchList();                                                  // Refreshing the List
 }

 fetchList() {                                                        // Fetching Function
   this.productService
     .getListProduct()
     .subscribe((data: Product[]) => (this.listProduct = data));
 }
 deleteProduct(p: Product) {
   let i = this.listProduct.indexOf(p);
   this.productService
     .deleteProduct(p.id)
     .subscribe(() => {
       this.fetchList();                                              // Refreshing the List
     });
 }
 saveProduct(product: Product) {
   let i = this.listProduct.indexOf(product);
   if (i != -1) {
     //update a product
     this.productService
       .updateProduct(product)
       .subscribe(() => (this.listProduct[i] = product));
   } else {
     //add a new product
     this.productService.addProduct(product).subscribe(() => {
       this.fetchList();                                              // Refreshing the List
     }, () => console.log('error'));
   }
   this.isForm = false;
   this.buttonString = 'Add New Product';
   this.inputProduct = new 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

Zone.assertZonePatched does not exist as a valid function

I am encountering an error message: Unhandled Promise rejection: Zone.assertZonePatched is not a function Despite importing zonejs correctly in my index.html file: <script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_ ...

Angular: Ensuring Elements inside mat-stepper within mat-dialog Adjust to the Height of the Dialog

I am dealing with a mat-dialog that contains a mat-stepper. Within this stepper, there is a step that includes a form with various elements such as a list, mat-card, and table. I need these elements to always fill the height of the dialog. Specifically, I ...

Connect twice with the Socket.IO client

Every time my socket io client connects to the server, it seems to happen twice. You can see what I mean by looking at this screenshot of the double connection. This project is built in Angular 2, so I'm coding in TypeScript: class Server { pr ...

Tips for communicating between an Angular 7 frontend and a Spring Boot backend server

After creating a server with Spring Boot that listens to @GetMapping("/portGroup/{portGroup}/date/{date}") I encountered a 400 "Bad Request" error when trying to query this endpoint. Can anyone guide me on the correct method to send a GET request to thi ...

Struggling to populate a table with data

I've previously sought help on this project and I'm still facing challenges. The code is messy with duplicate functions, making it hard to manage. Currently, my main issue is fetching data from Firebase and updating a table with it. <div cla ...

Ensuring TypeORM thoroughly examines all columns with the decorators in NestJS

Is there a method to ensure the uniqueness validator in the TypeORM entity inspects all columns and provides notifications for all detected errors collectively? Consider this schema as an example: import { BaseEntity, Column, Entity, PrimaryGenera ...

ensure that the data is loaded into the view prior to its display

Currently I am facing an issue while working with Ionic 2 and Angular 2. My challenge is to display some data in a view, but I am fetching this data from an API on the same page. However, when I attempt to display this data in the view, it appears as unde ...

Exploring the Enum Type in GraphQL Apollo Query

Within the server environment, I have defined the enum and query in the schema: type Query { hello: String! getData(dataType: DataType!): [DataPoint] } enum DataType { ACCOUNT, USER, COMPANY } ... Now, on the client s ...

Struggling with parsing JSON files in Angular 5?

Hello, I am currently working on a web application using Angular 5. I am facing an issue while trying to read a JSON file through an HTTP call. Despite the file being in the same folder, I keep getting a 404 error. Here is a snippet from my service.ts file ...

Testing Angular application using Cypress.io with a Google Login popup window

Has anyone experienced difficulties logging into a Google account using Cypress.io and the Google authentication pop-up window? Although I am able to open the window, Cypress is unable to locate the ID for the email input field. The specific error messag ...

The functionality to disable the ES lint max length rule is malfunctioning

In trying to disable an eslint rule in a TypeScript file, I encountered an issue with a regular expression that exceeded 500 characters. As a result, an eslint warning was generated. To address this, I attempted to add an eslint comment before declaring th ...

Starting the process of configuring Angular 5 with Express using TypeScript

Hi there! I am looking to create a fresh application using angular 5 and express (typescript for express as well). Do you have any helpful guides or tips that could assist me in reaching my objective? Appreciate all the help, Giuseppe ...

Please indicate the generator title (for example, nx generate @nrwl/workspace:library) specifically for Angular

Currently, I am expanding my knowledge in web development. While working with Angular, I encountered an issue when trying to create a new component. The error message reads "Specify the generator name (e.g., nx generate @nrwl/workspace:library)" after exec ...

Exploring the Magic of Angular 5 Reactive Forms: Step-by-Step Guide to Dynamically Implement Validators and Displaying Errors upon Form Submission

My goal is to dynamically manage the required validator for form fields. It seems to be working fine when the user interacts with the field before submitting the form, as it validates onBlur and onSubmit. However, if a user submits the form without interac ...

VueJS TypeScript with ChartJS - Unexpected Token '}' Parsing Error

I have integrated Chart.js into my Vue project. After installing chart.js and @types/chart.js using npm, I included a chart.d.ts file with the line declare module 'chart.js'; . Encountered an error which can be viewed https://i.sstatic.net/8npR ...

On which platform is the getFeatureInfo request constructed using Cesium?

Currently, I am working with Cesium and Angular. I am trying to locate where the request URL is generated for GetFeatureInfo in Cesium, but unfortunately I am unable to find it. My goal is to display feature information when clicking on the map. However, ...

Angular 2's .remove() method: removing elements like a pro

Consider a scenario where there is a list of 5 items, and the user should be able to delete a specific entry from that list. By using jQuery, you can target the delete button class and utilize 'this' to select its closest parent element, followed ...

What are the steps to locally set up the Angular.dev website?

The latest version of angular.dev has just been launched and made available as open source. I'm eager to set it up on my local machine, but I'm facing issues running yarn smoothly within the Node 18 container. Here's what I've attempted ...

utilize optional react useState typings along with JSDoc comments to ensure TypeScript checking for JavaScript code

Utilizing typescript's jsdoc support to type the provided javascript snippet: const [optionalNumber, setOptionalNumber] = useState(null) const handleClick = () => { setOptionalNumber(42) // ^-- Argument of type '42' is not ...

Encountered an error - 'SyntaxError: unexpected token: ':'' while attempting to load a JSON file for ngx-translate using the Karma test runner

I am currently in the process of setting up system tests for my Angular application. The app utilizes the TranslateModule (ngx-translate) in this manner: TranslateModule.forRoot({ defaultLanguage: 'de', loader: { provide: Tra ...