Issue in Angular form: Element removal from the DOM does not remove it at the specified index, instead removes the last item

I'm encountering an issue where the wrong element is being removed from the DOM. In my onDelete() method, I am deleting a specific FormControl at a certain index, but in the actual DOM, it's removing the last item instead of the intended one.

For example:

(The delete button should remove a formControl from a formArray and triggers onDelete())

  1. [input box] [delete button] <- when this button is clicked
  2. [another input box] [delete button]
  3. [another input box] [delete button] <- despite TypeScript removing the correct value, this gets deleted

TypeScript:

export class RecipeAddComponent implements OnInit, OnDestroy {
  // code block here

HTML:

<div class="mx-auto p2 root-container">
  <form [formGroup]="recipeForm" class="form-margin" (ngSubmit)="onSubmit()">
    <!-- HTML markup here -->
  </form>
</div>

Answer №1

Consider trying a different approach for your template syntax, specifically when iterating through an array of ingredients:

  • Use track by item instead of $index
  • (optional: define a separate variable index and pass it to the onDelete method instead of using $index)

Here's a suggested code snippet:

  @for (item of ingredientControls; track item; let index = $index;) {
    <div formArrayName="ingredients">
      <div class="container-with-delete">
        <mat-form-field class="example-full-width">
          <mat-label>Ingredient</mat-label>
          <input
            matInput
            type="text"
            [placeholder]="item.value"
            [formControlName]="index"
          />
        </mat-form-field>
        <button type="button" (click)="onDelete(index, 'ingredients')">
          <mat-icon>delete</mat-icon>
        </button>
      </div>
    </div>
    }

For additional information on this topic, check out this resource:

What is the @for tracking function?

The tracking function created via the track statement is used to make it easy for the Angular change detection mechanism to know exactly what items to update in the DOM after the input array changes.

edit:

refactor suggestion:

Create a separate method for constructing forms that accepts an object containing default or server data based on the isEditMode condition:

  • In the else section, move the form creation logic to a new method that constructs the form from the provided input object
    public constructForm(recipe:any) {
          
          // consider changing to `this.ingredients`
          // Alternatively, you may return form controls and apply them with the spread operator:
          // return {ingredients: ...}
          // Then,
          // this.recipeForm = new FormGroup({
          // ...returnedControls,

          ingredients = new FormArray<FormControl>([]);
          steps = new FormArray([]);
          prepTimes = new FormArray([]);
  
         this.recipeForm.patchValue(recipe);

          // include loops here
    }
  • Create a default data object

    defaultFormData = {
      ingredients: ['e.g. 2 spoons of sugar powder',...],
      steps: ['e.g. 2 spoons of sugar powder',...]
      // etc.
    };
    
  • Based on the value of isEditMode, provide either the default object or retrieve data from the server:
// If not in edit mode, use the default object
if (!this.isEditMode) {
  this.constructForm(this.defaultFormData);
} else {
  // Fetch data from the server
  this._recipeService.fetchRecipe(this.recipeId).subscribe((recipe) => {
    this.constructForm(recipe);

}  

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

Text transitions in a gentle fade effect, appearing and disappearing with each change

I want to create a smooth fade in and out effect for the text within a div when it changes or hides. After researching on Google and Stack Overflow, I found that most solutions involve adding a 'hide' CSS class and toggling it with a custom func ...

Unable to add JSON data to Javascript List Object? Consider using a combination of Node.JS and Firebase for a

router.get('/getMeals',function(req,res){ var mealsList = []; mealsList.push("bar"); mealsRef.on("value",function(data){ data.forEach(function(child){ console.log(child.val()); var newMeal = child ...

What are some ways to optimize Ajax requests for improved speed when multiple identical requests are made on a single webpage?

When the webpage is loaded, a block is dynamically created using an Ajax call to retrieve data from another page. This structure is then populated and added to a specific DOM element. However, multiple Ajax calls during page loads are causing delays. Is ...

What could be causing my if-else statement to malfunction in JavaScript?

I'm working on a form where certain conditions need to be met based on the selected order type. For instance, if a market order is chosen, the stop price and limit price should default to zero and become read-only fields. Similarly, selecting a limit ...

What are the reasons for the various methods available for importing my JS code?

Here is the structure of my folders: --public ----frontend.js --views ----fontend.ejs The frontend.js file is located inside the public folder, while the frontend.ejs file is in the views folder. In my HTML / EJS file, I included the JavaScript (fronten ...

The system is facing difficulty in accessing the property 'user_first_name' as it is currently undefined

I'm having trouble registering a user with expressjs/mongoose as I keep receiving the error: TypeError: Cannot read property 'user_first_name' of undefined at C:\Quiz webPolitica\server.js:20:24 at Layer.handle [as handle_request] ...

Dealing with bulkWrites in Mongoose and MongoDB: how to handle cast errors with finesse

When importing data into my app's database using MongoDB's bulkWrite operation, I encounter a challenge. The data may contain errors as it comes from an external source. To maintain the integrity of my data, I need to update my collection while s ...

The background image is not appearing on the div as expected

I've been attempting to create a div and set a background image for it using jQuery, but I seem to be facing issues. When I try setting the background color to white, it works fine. Here's the code snippet: function appendToDom(poster) { ...

What is the best way to use AJAX to load a PHP file as a part

I'm exploring different methods for making an AJAX call with an included file. Let's create a simple working example. Initially, I have my main index.php file which contains the following content. In this file, I aim to access all the data retur ...

Using source maps with Typescript in Webpack (source maps not visible while using webpack-dev-server)

I am currently experimenting with Typescript in combination with Webpack, utilizing the 'awesome-typescript-loader' plugin. However, I am encountering an issue where the source maps are not displaying in the browser when running webpack-dev-serve ...

AJAX Object Creation: Only Visible After Manual Refresh

Currently, I am in the process of building a basic to-do app that includes multiple different lists, each of which contains a variety of items. My main objective is to integrate AJAX functionality into the creation and display of lists on the lists#index p ...

Encountered an issue while attempting to assign a value to a property that is declared as [key in keyof T]

I am currently working on implementing a function that selects specific properties of an object. Here is the current function: const project = function<T>(object: T, projection: Projection<T>): Partial<T> { throw new Error("not imple ...

What is the best way to activate an alert or swal function just once instead of repeatedly?

I am just starting to learn Angular. Currently, I have an application that contains two variables related to the status of financial transactions. These variables are: tab1TrxMessage, which holds any important messages, and tab1TrxStatus that indicates wh ...

Access a JSON response within an HTML/JavaScript document

Can the scenario below be achieved? Here is the ajax response I received: HTML <body> <input type="text"></input> <div id="trydiv"></div> </body> JS $.ajax({ type: "POST", url: "json.php", ...

The Angular template-driven form featuring Material inputs will automatically reset itself when initialized

I am currently working on a simple template-based form in my application, utilizing material form fields. I have opted for this approach instead of a reactive one. The desired functionality is to display the form only when the user clicks on a button. Up ...

eliminate the offspring of a component (chessboard)

Hey there! I'm currently working on developing a chess game and I could really use your expertise to help me solve an issue. In my code, when I try to move a piece in the game, this is what happens: 1. First, I remove the existing piece from its cu ...

Creating a dynamic form with Angular 5 that includes a conditional required textarea

When the checkbox is clicked, a textarea will appear and is required [required]="otherVendorsChecked == true ? true : false". Even if I select the checkbox and then deselect it, the textarea input remains required. Any ideas on what could be going wrong? ...

What is the best way to navigate to the bottom of a page when new data is added?

I've created a chat feature in my Ionic app, but the issue is that when a user receives a new message while being on the chat screen, the view doesn't automatically scroll down to show the new message. The user has to manually scroll down to see ...

Tips for integrating highcharts plugins with highcharts-vue (highcharts vue wrapper)

Currently, I am utilizing the Vue wrapper for Highcharts called highcharts-vue(https://github.com/highcharts/highcharts-vue). However, I am facing an issue where I need to detect the event of a right mouse click (contextmenu) on the chart. To address this, ...

Tips for preventing a valid instruction from being identified as an error in NetBeans

As I work on my socket.io and node.js system in NetBeans 7.2, I encounter an issue every time I input a correct instruction like: io.sockets.in(channel_id).emit('new user', data); The problem lies in the ".in" part, which triggers an error high ...