Challenges with creating nested reactive forms

Attempting to create a dynamic form that is nested within 2 components. The functionality of the ParentComponent is running smoothly, but encountering issues with the ChildComponent. This ChildComponent utilizes ControlValueAccessor.

Inquiry: The fields are visible in the view, but changes made do not reflect in the parent component. Why is this happening? Are the functions for ControlValueAccessor implemented correctly?

child.component.html

<ul [formGroup]="fieldsForm">
    <li *ngFor="let field of fields">
      <label>
        <input type="checkbox" [formControlName]="field.$key">
        {{field.$key}}
      </label>
    </li>

</ul>

child.component.ts

import {Component, OnInit, Input, ChangeDetectionStrategy} from '@angular/core';
import {FormGroup, FormBuilder, NG_VALUE_ACCESSOR, ControlValueAccessor} from "@angular/forms";
import {NodeService} from "../../node.service";

@Component({
  selector: 'child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  providers: [
    {provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() =>ChildComponent), multi: true}
  ]
})
export class ChildComponent implements OnInit,ControlValueAccessor {

  public fieldsForm: FormGroup;
  public fields: any = [];

  @Input() currentFilter;
  @Input() formControlName;

  constructor(private fb: FormBuilder, private nodeService: NodeService) {
    this.fieldsForm = this.fb.group({});
  }

  ngOnInit() {
    this.getFilterValues(this.formControlName)
    .subscribe(fields => {
      const acc = {};
      this.fields = fields;
      fields.forEach(field => acc[field.$key] = [true]);
      this.fieldsForm = this.fb.group(acc);
    })
  )

  registerOnChange(fn: (value: any) => void) {
    this.fieldsForm.valueChanges.subscribe(fn);
  }

  registerOnTouched() {}

  getFilterValues(type) {
    return this.nodeService.getFilterValues(type, {
      query: { orderByValue: true, equalTo: 1 }
    })
  }

}

parent.component.ts

import {Component, OnInit, ChangeDetectionStrategy} from '@angular/core';
import {FormBuilder, FormGroup} from "@angular/forms";
import {Input} from "@angular/core/src/metadata/directives";
import {Subject} from "rxjs";

@Component({
  selector: 'filter',
  templateUrl: './filter.component.html',
  styleUrls: ['./filter.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ParentComponent implements OnInit {

  public form: FormGroup;
  public groupsForm:Subject<any> = new Subject();

  @Input() groups;
  @Input() currentFilters;

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({})
  }

  ngOnChanges() {
    const acc = {};
    this.groups.map(group => {
      acc[group] = [];
    });
    this.groupsForm.next(acc);
  }

  ngOnInit() {
    this.groupsForm.subscribe(groupForm => this.form =     this.fb.group(groupForm));

    // Detect changes from from
    this.form.valueChanges
     .subscribe(console.log)
  }

}

parent.component.html

<form [formGroup]="form" novalidate>
  <fieldset *ngFor="let group of groups">

    <child [formControlName]="group" [currentFilter]="currentFilters[group]"></child>

  </fieldset>
</form>

Devoted several weeks to developing this form. Explored both nested and single-component approaches. Utilizing ControlValueAccessor feels like the right path. Any assistance or guidance would be greatly appreciated. Thank you!

Answer №1

Why not consider registering a provider at a higher level, such as in the ParentComponent? This way, the NG_VALUE_ACCESSOR becomes available for the ChildComponent and its descendants.

My approach to integrating nested components with reactive forms involves passing the FormGroup to children as an @Input. Check it out on GitHub.

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 is the source of the compiler options in tsconfig.json?

Currently utilizing Typescript in NestJs, I have incorporated various packages. However, the specific package responsible for altering these settings remains unknown to me: "checkJs": false, "skipLibCheck": true Is there a method to ...

Angular 7 - ngForm and ngSubmit: Resubmitting outdated data

I have a form in Angular 7 set up like this: <form #payForm="ngForm" (ngSubmit)="onSubmit(payForm, $event)" method="POST" action="POST URL HERE"> <input type="hidden" name="requestParameter" [value]="stringToSend" /> <div class= ...

Stop any ongoing search requests in Angular 7 using Ng2SmartTable

My current setup involves Angular version 7.0.1 and ng2-smart-table version 1.4.0. The issue I'm facing is that each search within the table triggers a new API request to fetch data. What I actually want is for only the latest search request to be pro ...

What is the best way to pass form values from child components to parents when utilizing a value accessor implementation?

What is the most effective method to retrieve the values of a child component control group from a parent component? I have currently implemented this using value accessor, but I am curious about the best approach. You can check out the plunker demo I have ...

Utilizing Angular Material Table to present information efficiently

I have a unique data structure that I need to present using mat-table. dataSource= [[1,2],[3,4],[5,6]] In this structure, dataSource[0] always serves as the heading, with the rest of the array items representing its rows. Therefore, the expected output ...

Can we verify if strings can serve as valid property names for interfaces?

Let's consider an interface presented below: interface User { id: string; name: string; age: number; } We also have a method defined as follows: function getUserValues(properties:string[]):void { Ajax.fetch("user", properties).then( ...

"Exploring the versatility of ng-content in Angular 6: A comprehensive guide on

After diving into Angular recently, I decided to tackle creating a menu system in Angular 6. Here is the breakdown of my folder structure: https://i.sstatic.net/QCXP8.png Starting with my app.module.ts: import { BrowserModule, } from '@angular/plat ...

Bootstrap root.scss is showing an error about an undeclared variable called $theme-colors-rgb

My Angular project is configured for SASS, and I'm integrating Bootstrap 5.2 by importing the necessary scss files within the main style.scss file. My goal is to utilize the Bootstrap Grid and some basic components alongside Angular Material. The cur ...

Angular's HTTP client allows developers to easily make requests to

I am struggling with grasping the concept of async angular http client. In my Java backend, I have endpoints that return data in the same format but with different meanings. To handle this, I created the following code: export class AppComponent implement ...

Removing a nested data object in Angular with NGXS

I have successfully implemented the get and delete functions for posts in my Angular app. However, I am facing issues when trying to delete a comment within a post using NGXS. How can I access the comment inside the post in order to delete it? Here's ...

Obtaining the initial successful value within an array containing TaskEithers

As someone who is diving into functional programming and just beginning to explore fp-ts, I am grappling with understanding the util functions provided. My current challenge involves figuring out how to handle TaskEithers as fallbacks within an array. I h ...

Unveiling RxJs: The secret to extracting the notifier value using the takeuntil operator

I have a straightforward Rxjs timer set up that runs until a notifier emits a signal, it's pretty basic so far. enum TimerResult = { COMPLETE, ABORTED, SKIPPED }; _notifier: Subject<TimerResult> = new Subject(); notifier$: Observab ...

Issue with TypeScript: 'MongoClient' variable cannot be resolved

Just dipping my toes into TypeScript, I decided to convert a JavaScript file to TypeScript using WebStorm for the very first time. Although my code is functional, I keep receiving this warning: unresolved variable 'MongoClient' Additionally, ...

Error encountered: JSON.parse failed due to unexpected input at position 281

I've been struggling to find a solution, as my searches always turn up irrelevant answers. I hope someone can help me out with this issue. Thank you in advance for your assistance. TypeError: JSON.parse Error: Unexpected token at position:281 imp ...

Having trouble locating the withArgs() method of the Spy class when using Jasmine and TypeScript

As per the Jasmine documentation, there is a method called withArgs() in the Spy object. spyOn(someObj, 'func').withArgs(1, 2, 3).and.returnValue(42); In the TypeScript-adapted version, I am unable to locate this method. My project was initiali ...

Upload images using Ionic 3 from both camera and gallery seamlessly

Could you please assist with an issue I'm encountering in my ts file code? I am having difficulty sending an image to the server. Although it appears to be working as I receive a notification stating that the image has been successfully uploaded, I am ...

Error: The field 'password' is not found in the specified type

Hey, I'm fairly new to TypeScript and encountering an error with my express and MongoDB application. Let's take a look at my User.ts model. import mongoose from "mongoose"; interface IUser { username: string; password: string ...

Strategies for handling asynchronous requests and effectively presenting the retrieved data

On my HTML page, I have a badge component that shows the number of unread messages. Here is the HTML code: <button class="font" mat-menu-item routerLink="/message"> <mat-icon>notifications</mat-icon> <span [matBadgeHidden]="newM ...

Leveraging *ngFor to extract HTML content from ion-label

I've encountered an issue while using *ngFor in my HTML like this: <ion-slides #slides [options]="slideOpts"> <ion-slide class="numbers-wrapper" *ngFor="let questionNumber of numbers" (click)="clickQue ...

I am encountering challenges with submitting the form

I am encountering an issue where I want to submit the form on button click and navigate to the next page, but instead I get an error message saying: "Form submission canceled because the form is not connected". Does anyone have a solution for this problem ...