Difficulty with the value binding issue on input text produced by *NgFor

When using *ngFor in Angular to loop over an array and generate input text elements bound to the values in the array, I'm encountering some issues. The value is not binding correctly when a user inputs something into the text field.

I attempted to run changeDetection after updating the array but it did not resolve the problem.

In the code example below, I am dynamically generating input elements by clicking on an add button using an array of string values "test". The [ngModel] of the input is supposed to bind to the value inside the array, so all inputs should have the value "test".

However, when entering a value into the input field and then clicking on the add button, the generated input does not bind to the value in the array.

Link to Code Example

import { Component } from '@angular/core';
@Component({
  selector: 'my-app',
  template: `
    <button (click)="onAdd()">Add</button>
    <br/><br/>
    <input
      *ngFor="let d of data;let i = index;trackBy:trackByfn" 
      type="text"
      [ngModel]="data[i]"
    > 
    <br/><br/>
    data: {{data|json}}
  `,
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  data = ['test'];  
  onAdd() {  
    this.data.push('test');
  }
  trackByfn = (index) => index;
}

Answer №1

Take a look at a live example on StackBlitz.

This code demonstrates two-way binding using the syntax ---> [(ngModel)]. This allows you to keep track of variable changes and get new values.

import { Component } from '@angular/core';
@Component({
  selector: 'my-app',
  template: `
    <br/><br/>
    <input *ngFor="let d of data; let i = index; trackBy:trackByfn" 
    type="text" [value]="data[i]" [(ngModel)]="dataarray"> 
    <button (click)="onAdd(data[i])">Add</button>
    <br/><br/>
    data: {{data|json}}
  `,
  styleUrls: [ './app.component.css' ]
})
export class AppComponent {
  data = ["ssdsdsd"];
  datatosave: any;  
  onAdd(data1) {  
    this.data.push(this.datatosave);
  }
  trackByfn = (index) => index;
}

Answer №2

To enable Two-way Data Binding, it's necessary to switch from using [ngModel] to [(ngModel)].

If you want to learn more about angular data binding, check out this informative article:

import { Component } from '@angular/core';
@Component({
  selector: 'my-app',
  template: `
    <button (click)="onAdd()">Add</button>
    <br/><br/>
    <input 
      *ngFor="let d of data; let i = index; trackBy:trackByfn"
      type="text"
      [(ngModel)]="data[i]"
    /> 
    <br/><br/>
    data: {{data|json}}
  `,
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  data = ['test'];  
  onAdd() {  
    this.data.push('test');
  }
  trackByfn = (index) => index;
}

Update: Implementing Form Group

import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators, AbstractControl } from '@angular/forms';

@Component({
  selector: 'my-app',
  template: `
    <button (click)="onAdd()">Add</button>
    <div [formGroup]="form" *ngFor="let f of fields">
      <input type="text" [formControlName]="f" /> 
    </div>
    <div *ngFor="let f of fields">
      {{form.controls[f].value}}
    </div>
  `,
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  form: FormGroup = new FormGroup({
    test: new FormControl('test')
  });
  fields = ['test'];
  onAdd() {
    const length = this.fields.length;
    this.fields.push('test'+length);
    this.form.addControl('test'+length, new FormControl('test'));
  } // length to dynamically name the field
}

Note: Remember to include ReactiveFormsModule in your imports withinapp.module.ts

I have made some modifications to your stackblitz example: https://stackblitz.com/edit/angular-2t157s

Answer №3

Utilize the @ViewChildren directive to dynamically add elements. The onAdd() function pushes the last element of the inputs array to the data[]. Take a look at this example on StackBlitz for reference.

Sample code:

import { Component, ViewChildren, ElementRef, 
         QueryList, AfterViewInit } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
  <button (click)="onAdd()">Add</button>
  <br/><br/>
  <input #inputRef type="text" 
  *ngFor="let d of data; let i = index; trackBy:trackByfn"> 
  <br/><br/>
  data: {{data | json}}
  `,
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  data = ['test'];

  @ViewChildren("inputRef") inputs: QueryList<ElementRef>;

  onAdd() {
    let domElement = this.inputs.last as ElementRef;
    this.data.push(domElement.nativeElement.value);
  }

}

Dive deeper into the capabilities of @ViewChildren in the official Angular documentation.

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

Getting the id of a single object in a MatTable

I'm currently working on an angular 8 application where I've implemented angular material with MatTableDatasource. My goal is to retrieve the id from the selected object in my list: 0: {id: "e38e3a37-eda5-4010-d656-08d81c0f3353", family ...

Building with Angular seems to be dragging on forever

Working with Angular 6.7 on a finance application that consists of over 80 modules. When I run the build using the command: node --max_old_space_size=16384 ./node_modules/@angular/cli/bin/ng build --prod The build process takes more than 90 minutes to com ...

Merging Type-GraphQL and Typegoose through a Variety of Decorators

Using a combination of Type-GraphQl and Typegoose, I aim to streamline my data definitions by consolidating them into one source for both GraphQL schemas and Mongoose queries. Is it feasible to merge the two libraries in a way that allows me to describe bo ...

Personalized style for text overflow property

The application is created using Angular. Within a component, we have a div containing some text: <div>abcdefghijklmnop<div> Depending on the screen size, the text should either be fully displayed or clipped. I discovered the property 'te ...

Deciphering the Mysteries of API Gateway Caching

It seems like a common pattern to enable an API Gateway to serve an Angular Webapp by pulling it from S3. The setup involves having the API gateway with a GET request set up at the / route to pull index.html from the appropriate location in the S3 bucket, ...

Ways to avoid redundancy in Gitlab CI/CD when utilizing multiple stages

Currently, my workflow involves utilizing gitlab CI/CD for deploying my angular app on firebase. This process consists of 2 stages: build and deploy. image: node:11.2.0 stages: - build - deploy cache: paths: - node_modules/ build: stage: bu ...

Strange Node.js: I always avoid utilizing `require()`, yet encountered an unexpected error

For more information on this particular issue, please refer to this link It's quite puzzling as I haven't used the require() function in my code, yet I'm receiving an error telling me not to use it. How odd! The problematic code snippet i ...

What is the approach of Angular 2 in managing attributes formatted in camelCase?

Recently, I've been dedicating my time to a personal project centered around web components. In this endeavor, I have been exploring the development of my own data binding library. Progress has been made in creating key functionalities akin to those f ...

Looking for the location of the traceResolution output?

When I enable traceResolution in my tsconfig.json file, where can I expect to see the resulting output? { "compilerOptions": { "traceResolution": true, ... The --traceResolution flag enables reporting of module resolution log messages. You ...

To resolve the issue of expired tokens, we must implement a mechanism in Angular to detect when a token has expired. When a token expiration

When utilizing an angular interceptor to include the authorization token in the header, everything functions smoothly until the token expires. Following the expiration of the token, Laravel returns a token_expired error. My goal is to detect this error wit ...

Is it possible to utilize an enum for typing an array variable?

Is there a way to use an enum to define the valid types that an array can contain? I have been unable to find a solution so far, and I am curious if it is feasible. Below is the example code I have tried: interface User { name: string; } interface Ad ...

A guide on incorporating unique font weights into Material UI

Looking to customize the Material theme by incorporating my own font and adjusting the font weights/sizes for the Typography components. I am attempting to set 100/200/300/400/500/600/700 as options for each specific typography variant, but it seems that o ...

Differentiating elements from two array objects in typescript: a guide

I am facing an issue in extracting the different elements from two array objects. Here is my example: array1 = [{id: 1, a: "a", b: "b"}, {id: 2, c: "c", d: "d"}, {id: 3, e: "e", f: "f"}]; array2 = ...

Struggling with TypeScript Errors while Extending Theme Colors in Material UI React using TypeScript

Just started with typescript and feeling a bit lost, can someone offer some guidance? I'm working on a React project using material-ui with typescript. To add a new color the correct way, it needs to be added to a theme: const theme = createMuiTheme({ ...

Unique validation for matching passwords in Angular applications

Looking to incorporate a registration form into my angular/ionic app. The form consists of 6 fields within a formGroup (username, first name, last name, password, confirm password, gender). I am seeking to validate the data on the client side using Angular ...

ESLint has issued a warning indicating that the selector must be utilized as an element

Running Angular 12 and ESLint together has raised some issues for me. Whenever I run ng lint, ESLint reports a problem with the selector below. 10:13 error The selector should be used as an element (https://angular.io/guide/styleguide#style-05-03) @an ...

Issue with form using "target=_blank" to open PDF in web application home screen not functioning properly

I am encountering an issue in my Angular application where a form with target="_blank" successfully returns a PDF upon submission, but when accessed from the homescreen icon of the web-app in Android/Chrome, the new window opens blank without displaying th ...

Stop WebStorm from automatically importing code from a different Angular project within the same workspace

I currently have an angular repository that consists of two projects: a library and an Angular application. To link the library to my project, I utilized the npm link command. Within the package.json file, I specified the entry as follows: ... "my-lib ...

Guide on integrating a personalized theme into your Ionic 5 app

I'm looking to customize the theme of my Ionic 5 app by adding a red-theme to variables.scss @media (prefers-color-scheme: red) { :root { --ion-color-primary: red; Afterwards, I attempted to initialize it in index.html <meta name=" ...

What is the best way to transform this JSON data into an array of key-value pairs in JavaScript?

Dealing with nested JSON data can be challenging, especially when trying to extract key-value pairs efficiently. If anyone has suggestions on how to simplify this process and improve readability, please share your insights. The goal is to transform the ne ...