How can I retrieve the value of an array using ngForm in Angular 2?

One concrete example is a component I created that looks like this.

@Component({
    selector: 'home',
    template:
        `
        <form (ngSubmit)="onSubmit(f)" #f="ngForm">
            <input type="text" ngControl="people">
            <input type="text" ngControl="people">
            <input type="submit">
        </form>
    `
})
export class Home {
    onSubmit(f) {
        console.log(f.value);
    }
}

After entering "tom" and "bob" into each form field and clicking the "Submit" button, the console displays:

Object {people: "bob"}

However, my intended output would be:

Object {people: ["tom", "bob"]}

I wonder if it's possible to achieve an array value using ngForm?

Answer №1

In meeting my requirements, I have successfully utilized the ControlArray.

import {Component} from 'angular2/core';
import {FORM_DIRECTIVES, Control, FORM_PROVIDERS, FormBuilder} from 'angular2/common';

@Component({
        selector: 'home',
        template:
            `
            <form [ngFormModel]="sampleForm" (ngSubmit)="onSubmit(sampleForm)">
                <div ngControlGroup="people">
                    <div *ngFor="let item of sampleForm.controls.people.controls; let i = index">
                        <input type="text" ngControl='{{ i }}'>
                        <button (click)="delPerson(i)">Del</button>
                    </div>
                </div>
                <button (click)="addPerson($event)">Add</button>
                <input type="submit">
            </form>
        `,
        providers: [FORM_PROVIDERS]
    })
export class Home {

    sampleForm: any;

    constructor(private builder: FormBuilder) {
        this.sampleForm = this.builder.group({
            people: this.builder.array([new Control()])
        });
    }

    addPerson(event) {
        event.preventDefault();
        this.sampleForm.controls.people.push(new Control());
    }

    delPerson(i: number) {
        this.sampleForm.controls.people.removeAt(i);
    }

    onSubmit(f) {
        console.log(f.value);
    }
}

This solution has effectively met my needs. However, I find the syntax (

let item of sampleForm.controls.people.controls
) to be less elegant and I am uncertain about the appropriateness of using ngForm in this context.

Answer №2

To enhance your application, I propose creating a custom subcomponent that is compatible with ngModel and form controls for managing people:

const PEOPLE_VALUE_ACCESSOR = new Provider(
  NG_VALUE_ACCESSOR, {useExisting: forwardRef(() => PeopleComponent), multi: true});

@Component({
  selector: 'people',
  template: `
    <div>
      Person 1 : <input [(ngModel)]="person1" (ngModelChange)="doOnChange()"/><br/>
      Person 2 : <input [(ngModel)]="person2" (ngModelChange)="doOnChange()"/>
    <div>
  `,
  providers: [ PEOPLE_VALUE_ACCESSOR ]
})
export class PeopleComponent implements ControlValueAccessor {
  onChange = (_) => {};
  onTouched = () => {};

  writeValue(value:any):void {
    if (value!=null) {
      this.person1 = value[0];
      this.person2 = value[1];
    }
  }

  doOnChange(elt) {
    this.onChange([ this.person1, this.person2 ]);
  }

  registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
  registerOnTouched(fn: () => void): void { this.onTouched = fn; }
}

You can implement it as follows in your form:

<form>
  <div>
    <people #people="ngForm" ngControl="people"></people>
    people : {{people.value}}
  </div>
</form>

Upon using the associated control (people.value), you'll receive an array.

For a working example, refer to this Plunkr demo: https://plnkr.co/edit/ix8unZ58hvqojjAic0E3?p=preview.

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

What could be the reason for the exclusion of 'null' from the return type of Document.getElementById in VS Code?

Versions of VS Code: https://i.sstatic.net/nd5cD.png Experimenting with 'Type Narrowing' Code in VS Code has brought to my attention a discrepancy between the information provided by VS Code and TypeScript Playground: In VS Code, it shows that ...

When using tsdx with React, null values can prevent proper usage of hooks

Recently, I attempted to develop a React TypeScript component using tsdx for compilation and encountered a roadblock while debugging. The package appears to be successfully published and installed without any errors. However, when trying to use it, I consi ...

You are unable to elongate the interface 'http.IncomingMessage'. Were you intending to use 'implements' instead?

I have been struggling to execute the serve command for my angular project, encountering errors every time. Despite searching on Google for solutions, I have now reached a point where none of the answers seems to be helping. I recently downloaded a MEAN st ...

Having difficulty converting string columns/data to numerical values when exporting an Ag-Grid table to Excel with getDataAsExcel function

I am having an issue with exporting data from my ag-grid table to excel using the API method getDataAsExcel. The problem arises because I have a column containing only string values, while all other columns are numeric and displayed in the ag-grid table a ...

Setting up pagination in Angular Material can sometimes present challenges

After implementing pagination and following the guidelines provided here. This is my code from the app.component.ts file - import { Component, OnInit, ViewChild } from '@angular/core'; import {MatPaginator} from '@angular/material/paginat ...

Running pre-commit eslint autofix but encountering errors that do not exist

Encountering an issue with committing changes to a file due to a failed pre-commit eslint --fix task, displaying the following errors: × eslint --fix: C:\Users\user\source\repos\project\project-frontend\src\compone ...

Wait for the nested request to finish before returning the Observable

There are a pair of POST-requests within this function: function addArticle(request: IArticle) { const requestPath = `${this.backendUrl}/articles`; return this.http .post<IResponse<IArticleApiContract>>(requestPath, getArticleApiContra ...

Two components are loaded simultaneously by Angular

I encountered a strange bug in my Angular2 frontend application. After logging in, I see two components appearing simultaneously - the login component and the main component. https://i.sstatic.net/KFH4l.png In the screenshot above, the login functionalit ...

Excessive notification events are currently causing a blockage in the Angular app

Currently, I am utilizing Angular 7 in combination with SignalR on the backend for push notifications. At certain times, an overwhelming amount of notifications flood in, causing my application to become completely unresponsive. The SignalR service compon ...

Creating a dual-element display in React within a single frame

My code looks like this: <Box> <SomeIcon/> <HightlightSearch query={query}> {text} </HightlightSearch> </Box> The HighlightSearch function uses innerHTML to highlight query results in the child (text). It's a simpl ...

Encountering issues while trying to run npm install for an Angular 7 application, specifically receiving an error stating: "Module not found: @angular-devkit/build-ng-packagr." This error is hindering

I don't have much experience with JavaScript, node, npm, Angular, etc. My expertise lies in TypeScript as I am still a beginner. However, I recently inherited an application that requires maintenance to resolve a cross-site cookie issue. As I attempt ...

What is the reason behind useEffect giving warnings for unnecessary fields that are not included in the dependencies array?

After reviewing the documentation for useEffect, I am puzzled by the warnings I receive for every variable and function used within useEffect, despite not having a dependency on them. Take a look at my useEffect below: const [updatedComm, setUpdatedComm] ...

I am facing conflicts between vue-tsc and volar due to version discrepancies. How can I resolve this problem?

My vsCode is alerting me about an issue: ❗ The Vue Language Features (Volar) plugin is using version 1.0.9, while the workspace has vue-tsc version 0.39.5. This discrepancy may result in different type checking behavior. vue-tsc: /home/tomas/Desktop/tes ...

Ways to retrieve the identifier of a specific element within an array

After successfully retrieving an array of items from my database using PHP as the backend language, I managed to display them correctly in my Ionic view. However, when I attempted to log the id of each item in order to use it for other tasks, it consistent ...

What could be causing issues with my Angular and Express.js Server-Sent Events implementation?

Objective: Implement Server-Sent Events in Angular App with Express Backend Issue: Client does not receive Server-Sent Events Backend Implementation router.get('/options/:a/:b/:c', async (req, res) => { console.log('options endpoint c ...

Angular - The filter method cannot be used on Observables

I have a database with users who need to complete unique homework sessions. Each homework session has its own identifier, name, date, and other details. After fetching all the user's homework from the database, it is stored in a private variable call ...

What could be the reason for receiving an undefined user ID when trying to pass it through my URL?

Currently, I am in the process of constructing a profile page and aiming to display authenticated user data on it. The API call functions correctly with the user's ID, and manually entering the ID into the URL on the front end also works. However, wh ...

Encountering a service call error during the execution of Angular 2 unit tests using Jasmine

Struggling with testing an angular service, my TypeScript code seems correct but I keep getting an error in my test cases for "this.someFunction.show()" not being a function, even though it exists in my actual service. Here is what I'm attempting to d ...

Error in React: Trying to access property 'functionName' of an undefined object on click event

I am facing an issue while trying to click a button in my React component that is supposed to trigger a function with a parameter named "item" which is defined within the function. The pseudo-HTML snippet for this scenario looks like: <div>{item.cre ...

Angular HttpClient not recognizing hashtag

I'm trying to make a REST API call, but running into issues with the developerId parameter being sent incorrectly: let developerId = "123#212"; let url = \`\${Constants.BASE_URL}\${marketId}/developers/\${developerId}\`; retur ...