The type FormGroup<any> lacks the controls and registerControl properties compared to AbstractControl<any>

I've been developing a reactive nested form inspired by this YouTube tutorial - https://www.youtube.com/watch?v=DEuTcG8DxUI

Overall, everything is working fine, except for the following error - https://i.sstatic.net/bZHPV.png

Below are my files.

home.component.ts

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormArray } from '@angular/forms';
import { MrgformComponent } from '../mrgform/mrgform.component';

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

  MRGForm: FormGroup = new FormGroup({
    data: new FormArray([])
  });

  ngOnInit(): void {
    this.generateMRGForm();
  }

  generateMRGForm(): void {
    this.MRGForm = new FormGroup({
      data: new FormArray([
        MrgformComponent.addMGRRowItem()
      ])
    })
  }

  submitMRGForm(): void {
    console.log(this.MRGForm.value)
  }

  get dataArray(): FormArray {
    return this.MRGForm?.get('data') as FormArray;
  }

  addRow(): void { }

  removeRow(): void { }
}

home.component.html

<div class="">
    <div
        class="grid grid-cols-6 gap-x-16 py-5 px-4 text-sm text-gray-700 border-b border-gray-200 dark:border-gray-700">
        <div class="text-gray-500 dark:text-gray-400"></div>
        <div class="text-gray-500 dark:text-gray-400"></div>
        <div class="text-gray-500 dark:text-gray-400"></div>
        <div class="text-gray-500 dark:text-gray-400"></div>

        <div>
            <button type="button" (click)="addRow()"
                class="text-white block w-full bg-blue-600 hover:bg-blue-700 focus:ring-4 focus:ring-blue-200 font-medium rounded-lg text-sm px-4 py-2.5 text-center dark:focus:ring-blue-900">Add</button>
        </div>
        <div>
            <button type="button" (click)="removeRow()"
                class="text-white block w-full bg-blue-600 hover:bg-blue-700 focus:ring-4 focus:ring-blue-200 font-medium rounded-lg text-sm px-4 py-2.5 text-center dark:focus:ring-blue-900">Remove</button>
        </div>
    </div>

    <form [formGroup]="MRGForm" (ngSubmit)="submitMRGForm()">
        <app-mrgform *ngFor="let MRGChildForm of dataArray.controls" [MRGChildForm]="MRGChildForm"></app-mrgform>
        <div
            class="grid grid-cols-6 gap-x-16 py-5 px-4 text-sm text-gray-700 border-b border-gray-200 dark:border-gray-700">
            <div class="text-gray-500 dark:text-gray-400"></div>
            <div class="text-gray-500 dark:text-gray-400"></div>
            <div class="text-gray-500 dark:text-gray-400"></div>
            <div class="text-gray-500 dark:text-gray-400"></div>
            <div class="text-gray-500 dark:text-gray-400"></div>
            <div>
                <button type="submit"
                    class="text-white block w-full bg-blue-600 hover:bg-blue-700 focus:ring-4 focus:ring-blue-200 font-medium rounded-lg text-sm px-4 py-2.5 text-center dark:focus:ring-blue-900">Submit</button>
            </div>
        </div>
    </form>
</div>

mrgform.component.ts

import { Component, Input } from '@angular/core';
import { FormGroup, FormArray, FormControl } from '@angular/forms';


@Component({
  selector: 'app-mrgform',
  templateUrl: './mrgform.component.html',
  styleUrls: ['./mrgform.component.css']
})
export class MrgformComponent {

  propertyList: { id: string, pname: string }[] = [
    { id: '', pname: 'Select Property' },
    { id: 'PROP1', pname: 'Prop 1' },
    { id: 'PROP2', pname: 'Prop 2' },
  ];

  groupList: { id: string, gname: string }[] = [
    { id: '', gname: 'Select Group' },
    { id: 'GRP1', gname: 'Group 1' },
    { id: 'GRP2', gname: 'Group 2' }
  ];

  selectedProperty: string = '';
  selectPropertyChangeHandler(event: any) {
    this.selectedProperty = event.target.value;
    console.log('selectedProperty:', this.selectedProperty)
  }

  selectedGroup: string = '';
  selectGroupChangeHandler(event: any) {
    this.selectedGroup = event.target.value;
    console.log('selectedGroup:', this.selectedGroup)
  }

  @Input()
  MRGChildForm: FormGroup = new FormGroup({
    property: new FormControl(''),
    group: new FormControl(''),
    variableName: new FormControl(''),
    minValue: new FormControl(0),
    maxValue: new FormControl(0)
  });

  static addMGRRowItem(): FormGroup {
    return new FormGroup({
      property: new FormControl(''),
      group: new FormControl(''),
      variableName: new FormControl(''),
      minValue: new FormControl(0),
      maxValue: new FormControl(0)
    });
  }

}

mrgform.component.html

<form [formGroup]="MRGChildForm">
    <table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
        <thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
            <tr>
                <th scope="col" class="py-3 px-6">
                    Propert
                </th>
                <th scope="col" class="py-3 px-6">
                    Group
                </th>
                <th scope="col" class="py-3 px-6">
                    Variable Name
                </th>
                <th scope="col" class="py-3 px-6">
                    Min Value
                </th>
                <th scope="col" class="py-3 px-6">
                    Max Value
                </th>
            </tr>
        </thead>

        <tbody>
            <tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
                <td class="py-4 px-6">

                    <select formControlName="property" (change)="selectPropertyChangeHandler($event)">
                        <option *ngFor="let property of propertyList; index as i" value="{{property.id}}">
                            {{property.pname}}
                        </option>
                    </select>

                </td>
                <td class="py-4 px-6">
                    <select formControlName="group" (change)="selectGroupChangeHandler($event)">
                        <option *ngFor="let group of groupList; index as i" value="{{group.id}}">
                            {{group.gname}}
                        </option>
                    </select>
                </td>
                <td class="py-4 px-6">
                    <input formControlName="variableName" type="text" id="variable-name"
                        class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
                </td>
                <td class="py-4 px-6">
                    <input formControlName="minValue" type="text" id="min-input"
                        class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
                </td>
                <td class="py-4 px-6">
                    <input formControlName="maxValue" type="text" id="max-input"
                        class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
                </td>
            </tr>
        </tbody>
    </table>
</form>

I've searched and experimented with various solutions to fix this issue. However, I believe there's something crucial that I'm overlooking. Any assistance would be greatly appreciated.

Answer №1

Solution 1

To bypass type checking, you have the option to utilize the $any() type cast function.

<app-mrgform 
  *ngFor="let MRGChildForm of dataArray.controls" 
  [MRGChildForm]="$any(MRGChildForm)"
></app-mrgform>

Solution 2

You can create a custom function that casts AbstractControl to FormGroup.

childFormToFormGroup(form: AbstractControl): FormGroup {
  return form as FormGroup;
}
<app-mrgform
  *ngFor="let MRGChildForm of dataArray.controls"
  [MRGChildForm]="childFormToFormGroup(MRGChildForm)"
></app-mrgform>

Check out the Demo on StackBlitz

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

Updating a null value within the database was done successfully

Currently, I am working with angular CLI version 8.1.0 and have a user list displayed on a mat table. Upon clicking on a specific user, a new page opens up containing two buttons - "approve" and "reject". The issue I am facing is that when I click on "ap ...

What is the best method for loading resources from routes such as /page/:id/subpage and more?

The current structure of my app component is as follows: <app-navigation></app-navigation> <router-outlet></router-outlet> with defined routes: const appRoutes: Routes = [ { path: 'items', component: ListComponent }, ...

Tips for minimizing disagreements while implementing optional generic kind in TypeScript?

An issue arises in StateFunction due to its optional second generic type that defaults to a value. Even when omitting this second generic, undefined still needs to be passed as an argument, which contradicts the idea of it being optional. While making arg ...

Implementing a builder pattern with @Ngrx/Store

Feeling a bit uncertain... I'm wondering if it's suitable, awesome or not advisable to employ a builder pattern to retrieve API response and then apply the builder pattern on that response before storing it in @ngrx/store? And later on when acces ...

Protractor syncing with an Angular page following redirection to an Auth0 non-Angular page

My Angular web application utilizes Protractor for end-to-end tests. Recently, I implemented OAuth0 authentication into my app. To disable Angular synchronization before redirecting to the non-Angular OAuth0 page, I use await browser.waitForAngularEnabled( ...

Difficulty retrieving information using AngularJS service post selection of item

Currently, I am working on a project involving an AngularJS application. While using the service testPanelService, I encountered a problem where selecting an item from a list correctly logs the details of the selected item. However, when attempting to fetc ...

Angular 13 encounters issues loading Bootstrap and JS files whenever the route button is clicked

As a beginner in Angular, I am currently working on converting HTML templates to Angular for the purpose of learning. However, I have encountered an issue when navigating to the signup page from the home's router link. The bootstrap and JS files are n ...

Is it possible to have routing only within child components in Angular 2?

I have set up a main component as the root component <tracker-module></tracker-module> Within the main component, there are sub-components structured like this: <header></header> <left-navigation></left-navigatio ...

Cease the generation of dynamically produced sounds

I am encountering an issue in Angular where I am unable to stop playing an audio from a service. Below is my play() method: play(item: string): void { const audio = new Audio(); audio.src = item; audio.load(); audio.play(); } In order to stop all ...

Integrity parameter in Angular2+ is utilized for ensuring the integrity of a local script file

I have encountered an issue with my AngularJS project. I have 2 scripts located in the asset folder and I generated integrity hashes for them using . While everything works fine on my localhost, when I upload it to the server, only Internet Explorer seems ...

Tips for eliminating nested switchMaps with early returns

In my project, I have implemented 3 different endpoints that return upcoming, current, and past events. The requirement is to display only the event that is the farthest in the future without making unnecessary calls to all endpoints at once. To achieve th ...

Tips for navigating the material ui Expanded attribute within the Expansion Panel

After looking at the image provided through this link: https://i.stack.imgur.com/kvELU.png I was faced with the task of making the expansion panel, specifically when it is active, take up 100% of its current Div space. While setting height: 100% did achi ...

Steps for utilizing Bazel to compile TypeScript

Calling all Bazel (Blaze) experts: I'm curious about the best method for integrating Bazel as a build system for cutting-edge web applications built in Typescript. Is there a preferred setup or perhaps a template that demonstrates this integration? T ...

Retrieve information and transform it into a dynamic variable using Firebase

I am trying to retrieve data from the current user, specifically their company named "ZeroMax", and then store this data in a global variable. The purpose of this variable is to define the path for Firebase. I believe my code gives a clear understanding of ...

Struggling to understand how to define and utilize Static variables in TypeScript? If you're finding that they are consistently coming up

export class myClass implements OnInit { counter = 0; static counter: any; onListItemClick(PackDef: PackDefinition): void { this.itemClicked.emit(PackDef); this.counter++; console.log(this.counter); } } and.. import { myClass } from '. ...

How can I display an error message if the checkbox is not selected upon form submission?

If none of the checkboxes are selected, an error message should be displayed. The error message should be hidden when a checkbox is checked, but it's currently visible initially and disappears when unchecked. I would greatly appreciate your help. Than ...

Conceal the header and the navigation tabs at the bottom while scrolling - Ionic version 3

Is there a way to conceal the header and footer (tabs at the bottom) as the user begins scrolling down vertically and then bring back the tabs and header when scrolling back up? I would appreciate any tutorials or documentation guides. https://i.sstatic ...

md-input-container malfunctioning

I am facing an issue with the code using "@angular/material": "^2.0.0-beta.1" import { MaterialModule, MdIconRegistry, OVERLAY_PROVIDERS, MdInputContainer, MdInputDirective } from '@angular/material' .... <md-input-container> <i ...

Navigating with Angular 4's router and popping up modals

I have an Angular 4 SPA application that utilizes the Angular router. I am looking to create a hyperlink that will open a component in a new dialog using Bootstrap 4. I am able to open modal dialogs from a function already. My question is, how can I achi ...

Tooltip implementation in Angular side bar is malfunctioning

I have integrated my angular 7 project side bar with a Tooltip from Angular Material, but I am facing issues with it not working properly. Can anyone guide me on how to correctly add the Tooltip functionality? Thank you. sidebar.component.html <ul cl ...