Successfully initializing FormArray values using patchValue method

In my application, I have a table of cashflows where each cashFlow consists of a varying number of periods. When a cashflow is clicked, I am attempting to populate a component so that the period values can be edited. The cashflow name along with the start and end dates are automatically filled in. Additionally, there is an array of periods with text boxes displayed for each period.

Despite my efforts, I am facing difficulties in displaying the initial values in the textboxes.
I have tried using patchValue or setValue methods without success.

I have meticulously gone through 12 related questions on Stack Overflow for guidance. While one suggestion gave me an idea to test, it did not provide a solution to my issue.

Below is the code snippet from cashFlowDetailComponent.ts:

 // Angular imports
import { Component, OnInit , Input, Output, ElementRef} from '@angular/core';
import { ReactiveFormsModule, FormBuilder, FormGroup, FormArray, FormControl, ValidatorFn } from '@angular/forms';
import {cashFlow, cashFlowPeriod} from '../cashflow'
import { IMyDpOptions, IMyDateModel, IMyDate } from 'mydatepicker';


@Component({
  selector: 'app-cashflow-detail',
  templateUrl: './cashflow-detail.component.html',
  styleUrls: ['./cashflow-detail.component.css']
})
export class CashflowDetailComponent implements OnInit {

  // Properties declaration
  myFormGroup: FormGroup;
  myCashFlow: cashFlow;

  constructor(private fb: FormBuilder) {}

  buildForm(cf_: cashFlow): void {
    this.myFormGroup = null;
    this.myCashFlow = cf_;
    if (cf_ == null) { return; }
    const a :FormArray = this.fb.array([]); 

    this.myCashFlow.periods.forEach(cfp => {
      a.push(this.cfpGroup(cfp));
    })

    this.myFormGroup = this.fb.group({
      cashFlowName: this.myCashFlow.cashFlowName,
      startDate: this.threePartDateFromDate( this.myCashFlow.startDate),
      endDate: this.threePartDateFromDate( this.myCashFlow.endDate),
      periods:a
    });

     // Trying to set initial values in textboxes
       this.myFormGroup.controls['periods'].controls[i].controls['value1'].setValue(this.myCashFlow.periods[i].value1);
  }

  cfpGroup(cfp_ : cashFlowPeriod) :FormGroup{
    const g : FormGroup = this.fb.group({
      value1: cfp_.value1
    });
    return g;
  }

  threePartDateFromDate(d_: string): any {
    const date_ = new Date(d_);
    return {
      date: {
        year: date_.getFullYear(),
        month: date_.getMonth()+1,
        day: date_.getDate()
      }
    };
  }
}

Here is the template being used:

<div *ngIf="myCashFlow && myFormGroup" [formGroup]="myFormGroup">

  <table style="margin:7px 7px 7px 7px">
        <tr>
      <td class="fieldLabel">Cash Flow Name</td>
      <td>
        <input type="text"
               formControlName="cashFlowName"
               style="width:175px;" />
      </td>
    </tr>


  </table>

  <table border="1">
    <tr>
      <td *ngFor="let cfp of myCashFlow.periods,let i=index">{{cfp.periodName}}</td>
    </tr>
    <tr>
      <td *ngFor="let cfp of myCashFlow.periods, let i=index" style="padding:7px;">
        <input type="text"
               [id]="cfp.periodName"
               style="width:35px;" />
      </td>
    </tr>
  </table>

</div>

Answer №1

Big thanks to saksham for recommending I try using stackblitz for this project!
Every day is a chance to learn something new, it seems.

You can find the latest version here.

I managed to solve the issue by carefully comparing the stackblitz code with an example provided by vic rubba found here.

  1. The section in my file that includes ngFOR needed a formArrayName="periods" without brackets.
  2. My file required a [formGroupName]="periodIndex", where periodIndex represents the index used in the loop. Any further explanation on this would be greatly appreciated as it was the final piece of the puzzle.
  3. The form element needed formControlName="value1" without brackets.

After reading numerous articles about FormGroup, FormArray, and patchValue over the past couple of days, points 2 and 3 had somehow gone unnoticed. I look forward to revisiting those articles soon.

I hope these insights are helpful to someone facing similar challenges.

The complete HTML template can be viewed on stackBlitz, but I'm including it here so you can see how my 3 key points fit into the context:

   <table border="1">
    <tr>
      <td *ngFor="let cfp of myCashFlow.periods, let i=index">{{cfp.periodName}}</td>
    </tr>
    <tr formArrayName="periods">
      <td *ngFor="let item of myFormGroup.get('periods').controls, let periodIndex=index"
          style="padding:7px;"
          [formGroupName]="periodIndex">
        <input type="text"
               formControlName="value1"
               style="width:35px;" />
      </td>
    </tr>
  </table>

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

Error: The argument provided, 'ParsedQs', cannot be assigned to parameter XXXX

I have a unique function along with an interface that defines its single argument: interface AnotherInterface { property1: string; property2: string; } function processData(data: AnotherInterface): Promise<any> { return Promise.resolve(d ...

What is the best way to free up memory after receiving responseText in a continuous streaming request?

Utilizing xmlHTTPRequest to fetch data from a continuous motion JPEG data stream involves an interesting trick where responseText can populate data even before the request is completed, since it will never actually finish. However, I have encountered some ...

Displaying webpack errors within gulp is a simple process

My TypeScript project utilizes webpack for transpilation, and gulp for managing build tasks. Let's consider this simple task to illustrate my query: var webpack = require('webpack'); var webpackStream = require("webpack-stream"); gulp.task ...

Creating an Object with Quoted Key in JavaScript/Typescript for MongoDB's '$push' Feature

Struggling to format the data in order to add an element into a nested array within MongoDB. Currently attempting this in TypeScript: var data = {$push:{"foo.12.bar":{ prop1: prop1, prop2: prop2, // referenced values above this code snippet ...

Determining the generic type argument of a class can be unsuccessful due to the specific properties within that class

Why is it that Typescript sometimes fails to infer types in seemingly simple cases? I am trying to understand the behavior behind this. When Typescript's Type Inference Goes Wrong Consider the scenario where we have the following class declarations: ...

Establishing API cookies in a Single Page Application

Scenario In the development of my single-page application (SPA), I have separated the frontend and backend components onto different domains: mywebsite.com myapi.com For simplicity, I am utilizing cookies for authentication. Upon signing in, the server ...

Access to private members is restricted when redefining a class method

After defining a private member with #, attempting to redefine a member that utilizes this private member will result in the inability to access it: class Foo { #secret = "Keyboard Cat"; method() { console.log(this.#secret); } } ...

In Typescript, an interface is defined where the "id" property is required to be a number, while all other properties must be of

I am in need of creating an interface to represent data received from the server, where the id is a number and all other properties are strings. This is what I attempted: interface AnyChartsData { id: number; [key: string]: string; } However, I enco ...

Angular Placeholder Positioned at the Top

Hello, I am a beginner in Angular and need to create an input field that looks like this: https://i.sstatic.net/LUXfJ.png Everything is going fine except for the Vorname placeholder at the top. How can I place it there? Currently, I am utilizing Angular ...

Items added to localStorage will not be able to store objects that have keys with array values

There seems to be an issue with how localStorage.setItem stores object values when the object contains keys with array values. var obj = data : { cachedat : ['1' , 2 , 3] }; localStorage.setItem('data' , JSON.stringify(obj) ); However, ...

Oops! It seems like you forgot to indicate a command before proceeding. Make sure to check out the available commands using '--help'

I keep encountering the following problem: Error: A command must be specified before proceeding. Use '--help' to see the available commands. whenever I try to use an ng command. ...

Updating values - trigger modifications on each subsequent value [BehaviorSubject.onBeforeNext?]

Let's say we have a basic BehaviorSubject: this.countryOfBirth$ = new BehaviorSubject<CountryEnum>(null); get countryOfBirth() { return this.countryOfBirth$.value; }; set countryOfBirth(val: CountryEnum) { this.countryOfBirth$.next(va ...

Analyzing an array of objects

Is there a way to filter an array of objects to only include elements that have 'text' containing 'ild'? For example, consider the following array: public data: any[] = [ { treeViewKey:0, id: 1, text: 'Root Node 1&a ...

Enhance the functionality of MatOption by developing a component that allows users to easily select

To make my life easier, I want to create a shared component that can select or deselect all elements in a mat-select. This way, I won't have to repeatedly implement the same functionality in my app. After considering different options, I came across ...

Switch button - reveal/conceal details

I am looking for assistance in toggling the visibility of information when clicking on an arrow icon. I have attempted to use JavaScript, but it was unsuccessful. My goal is to hide the information below by clicking on the downward-facing arrow image , an ...

Transforming query language from jQuery to Pure JavaScript

I have the following jQuery code that I am attempting to remove and convert into standard JavaScript: $('.switch').click(()=>{ $([".light [class*='-light']", ".dark [class*='-dark']"]).each((i,ele)=& ...

Sending data to a parent component from a popup window in Angular Material using a button click while the window is still open

How can I retrieve data from an Angular Material Dialog Box and send it to the Parent component? I am able to access data after the dialog box is closed. However, I am wondering if there is a way to retrieve data while the dialog box is still open, especi ...

How can a component access its own template specified in the @Component decorator?

@Component({ selector: 'base-comp', template: '<div>hello</div>' <-- how to get this }) export class BaseComponent { someMethod( ) { <-- referenced here } Is there a way to access the entire template i ...

Converting JSON to Date in ES6/TS with Angular 2

Below is the JSON data: let JSON_RESPONSE = `{"birthDates": ["2017-01-02","2016-07-15"]}` There is a TypeScript object called Children with an array of Date objects and an ES6 constructor: class Children { birthDates: Date[] = [] constructor(values ...

Having trouble with Ionic 4 navigation not triggering after a single click, requiring multiple clicks to navigate

I have a long list of items, around 40 in total, that load a page describing each item with photos, URLs, and other content. However, I find that I need to click two to three times before reaching this page. I suspect that the excessive use of HTML compone ...