Dynamic Angular select options with ngFor causing cascading changes in subsequent selects

In my Angular 5 project, I am attempting to create a set of three <select> elements using *ngFor. I came across a helpful thread on Stack Overflow that provided some guidance (check it out here). However, I've encountered an issue where the select elements are not independent - changing one affects the others, except for the third one. This is likely due to all selects sharing the same list of options. While this behavior makes sense, I want each select to be completely separate.

Below is the code snippet for looping through the 3 select elements with *ngFor:

<div class="col-sm-3" *ngFor="let groupField of selectedGroupingFields; let i = index;">
<select class="form-control col-sm-6" name="groupField{{i}}" [(ngModel)]="selectedGroupingFields[i]" (ngModelChange)="groupByFieldName($event, i)">
    <option value=""></option>
    <option [ngValue]="field.id" *ngFor="let field of columnDefinitions">{{field.name}}</option>
</select>

The collections used in this scenario are structured as follows:

selectedGroupingFields: string[] = ['', '', ''];    
columnDefinitions = [
  { id: 'title', name: 'Title'}, 
  { id: 'duration', name: 'Duration'},
  { id: 'percentComplete', name: '% Complete'},
  { id: 'start', name: 'Start'},
  { id: 'Finish', name: 'Finish'},
  { id: 'cost', name: 'Cost'},
  { id: 'effortDriven', name: 'Effort-Driven'}
];

To demonstrate the problem, I have created a function that changes the first select element when a button is clicked:

changeFirstGroupBy() {
  this.selectedGroupingFields[0] = 'title';
}

When executing this function, both the first and second select elements are affected. Curious about this unexpected behavior, I decided to manually create each select element in the HTML without using ngFor:

// Code example showing manual creation of individual select elements goes here...

Surprisingly, creating the select elements individually worked as intended, despite being structurally similar to the looped version. Moreover, changes made to the last select element also unexpectedly impact the second select. The mystery deepens...

If curious, check out this animated GIF depicting the issue: https://i.sstatic.net/TPAOD.gif

EDIT

I attempted switching from two-way binding to one-way binding but observed no change in behavior (

[ngModel]="selectedGroupingFields[i]"
).

ANSWERED

Update: The solution described above has been successfully implemented in one of my Open Source projects, Angular-Slickgrid. Visit the GitHub repository here, and explore the functionality in action at this demo link. Many thanks for your support!

Answer №1

To tackle this issue, consider implementing a trackBy function within the usage of the ngFor directive:

<div ... *ngFor="let groupField of selectedGroupingFields; let i = index; trackBy: trackByFn">
  <select ... name="groupField{{i}}" [(ngModel)]="selectedGroupingFields[i]" (ngModelChange)="groupByFieldName($event, i)">
    <option value=""></option>
    <option [ngValue]="field.id" *ngFor="let field of columnDefinitions">{{field.name}}</option>
  </select>
</div>

In this case, ensure that the trackByFn method returns the item's index:

trackByFn(index, item) {
  return index;
}

A live demonstration can be found in this StackBlitz implementation.

Answer №2

Hello! You have implemented two-way data binding in your code.

[(ngModel)]=selectedGroupingFields[i]

If you want to achieve the desired functionality, you can modify it as shown below:

<div class="col-sm-3" *ngFor="let groupField of selectedGroupingFields; let i = index;">
 <select class="form-control col-sm-6" name="groupField{{i}}" [ngModel]="selectedGroupingFields[i]" (ngModelChange)="groupByFieldName($event, i)">
  <option value=""></option>
  <option [ngValue]="field.id" *ngFor="let field of columnDefinitions">{{field.name}} 
 </option>
</select>

You can view a working example by clicking on this link: Link

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

The Angular parent component is able to detect changes in the ng-content child component

I am looking for a way to have a function execute in my parent component when an event is emitted from my child component. The child component is inserted into the parent using ng-content. I have simplified the code but I am struggling to get the child com ...

Discovering the bottom scroll position in an Angular application

I am working on implementing two buttons on an Angular web page that allow the user to quickly scroll to the top and bottom of the page. However, I want to address a scenario where if the user is already at the very top of the page, the "move up" button sh ...

Dropdown with no selected option

Having some trouble with the p-dropdown element in Angular5 and primeng library. Specifically, when dealing with a large entity called Consignment that has multiple fields, I notice that the selected values on several p-dropdown elements (in this case, the ...

The React Hook Form's useFieldArray feature is causing conflicts with my custom id assignments

My schema includes an id property, but when I implement useFieldArray, it automatically overrides that id. I'm utilizing shadcn-ui Version of react-hook-form: 7.45.0 const { fields, append, remove, update } = useFieldArray<{ id?: string, test?: n ...

Encountering errors in Visual Studio when trying to work with node_modules directories that have a tsconfig

In my current project, there is a tsconfig.json file located in the root directory. Strangely, Visual Studio keeps throwing errors related to other instances of tsconfig.json found in different packages, as shown below: https://i.sstatic.net/T7Co2.png Ev ...

Instructions for inserting a hyperlink into a column of a table with the *ngFor directive in Angular2

I currently have a table with 4 columns: Name, ID, Department, and City. I am fetching both the row data and column data as an array from a TypeScript file and iterating through them using *ngFor. Below is a snippet of my code: <tbody> <tr *ng ...

`Incorporate concurrent network requests in React for improved performance`

I am looking to fetch time-series data from a rest service, and currently my implementation looks like this async function getTimeSeriesQuery(i) { // Demonstrating the usage of gql appollo.query(getChunkQueryOptions(i)) } var promises = [] for(var i ...

ng-for loop not properly rendering array of collections in table cells

I've been working on developing a MEAN Stack application that deals with mongoDB data related to hostels. hostels { "_id" : ObjectId("5e3c21c03d8d54b35af796ed"), "Hostel" : "The traveler's Lodge", "Rooms" : 23, "Customer" : [ { ...

Get the most recent edition (10th version) of ngx-bootstrap to use with Angular 15

According to the official website, the 10th version of ngx-bootstrap is compatible with Angular 15: Angular (14.x.x - 15.x.x) ngx-bootstrap (10.0.0) However, when I try to install it (npm install ngx-bootstrap@latest), I encounter an error: https://i.sst ...

Angular displays error ERR_UNKNOWN_URL_SCHEME when attempting to retrieve an image saved in a blob

As I transition my app from Electron to Angular, one of my main objectives is to display an image uploaded by a user. Here's how I attempted to achieve this: page.component.ts uploadImageFile(){ fileDialog({}, files =>{ //Utilizing the fileDi ...

Creating a mongoDB query that matches elements in an array of subdocuments with elements in a Typescript Array

In my database, I have stored various Events using mongoDB. Each event comes with multiple fields, including an array of genres, which consists of subdocuments like {genre and subGenre}. For instance, an event could be classified as {genre: "music", subGe ...

Encountering a 400 error when attempting to make a

After recently starting to use angular5, I encountered an error when attempting to insert a new row of data into a table. The error message was Failed to load resource: the server responded with a status of 400 (Bad Request) I've experimented with bo ...

The installation of bower angular-card-input failed during the execution of the Jenkins build script due to an HTTP request

I encountered an issue when trying to run a bower script for building a frontend in Angular: When executing the bower command, I received an error regarding git fetch from the following link: https://github.com/angular-ui/ui-utils.git, with exit code ...

Creating an interface for writing types in Firebase functions/storage/database

What are the TypeScript types for Firebase functions, storage, and admin? I'm fairly new to TypeScript and currently in the process of updating my JavaScript code to TypeScript. Within my code, I am generating a context object. const context = { ...

Tips for creating ternary operator logic that account for numerous conditions and optional parameters:

Trying to create a logic for my validator functions that involves using objects as errorMaps for input validation. In the code snippet provided, args.drugName is an optional field. If the user provides text, we want to ensure it is greater than 3 letters; ...

react-navigation hook for navigating

Currently, I am utilizing the react-navigation hook and instead of repeating the hook in various components, my goal is to pass navigation as a prop. const navigation = useNavigation(); ... <MyButton resetLocation={resetLocation} navigation= ...

When working with create-react-app and TypeScript, you may encounter an error stating: "JSX expressions in 'file_name.tsx' must

After setting up a React project with TypeScript using the CLI command create-react-app client --typescript, I encountered a compilation error when running npm start: ./src/App.js Line 26:13: 'React' must be in scope when using JSX react/r ...

Why does Material-UI's "withStyles()" not function properly with a specified constructor in Typescript?

Update: Please note that there was an issue with the constructor generated by IntelliJ IDEA, but it has been fixed. You can find more details here: I'm exploring the use of Material-UI in my application, and I've encountered some challenges wit ...

How can we identify all the foreign_key1 ids from a MySQL join table that have a specific foreign_key2 assigned to them that is within a specified list?

I have a scenario where I have two tables, Table A and Table B, connected by a many-to-many relationship. Table A: ID --- 1 2 3 Table B: ID --- 4 5 6 7 Table AB: ID | A_ID | B_ID ---------------- 8 | 1 | 4 9 | 1 | 5 10 | 1 | 6 11 | 1 | 7 ...

Mastering mapped types to replace properties in Typescript

I have created a Factory function where it takes an object as input and if that object contains specific properties, the factory transforms those properties into methods. How can I utilize mapped Types to accurately represent the type of the resulting obj ...