Why am I getting the "Cannot locate control by name" error in my Angular 9 application?

Currently, I am developing a "Tasks" application using Angular 9 and PHP. I encountered a

Error: Cannot find control with name: <control name>
issue while attempting to pre-fill the update form with existing data.

Here is how the form is structured:

<form [formGroup]="updateTask" name="edit_task_form">
  <mat-form-field appearance="standard">
    <mat-label>Title</mat-label>
    <input matInput placeholder="Title" formControlName="title" placeholder="Title">
  </mat-form-field>
  <mat-form-field appearance="standard">
    <mat-label>Short Description</mat-label>
    <input matInput placeholder="Short description" formControlName="short-description" placeholder="Short Description">
  </mat-form-field>
  <mat-form-field>
    <mat-label>Category</mat-label>
    <mat-select formControlName="tags">
      <mat-option *ngFor="let category of categories" [value]="category.id">{{category.name | titlecase}}</mat-option>
    </mat-select>
  </mat-form-field>
  <mat-form-field appearance="standard">
    <mat-label>Full Description</mat-label>
    <textarea matInput formControlName="full-description" placeholder="Full Description"></textarea>
  </mat-form-field>
  <div class="text-center">
    <button mat-flat-button type="submit" color="accent" [disabled]="updateTask.pristine || updateTask.invalid">Update</button>
  </div>
</form>

In my component file, I have included:

I am importing the following modules at the beginning:

import { Component, OnInit } from '@angular/core';
import * as _ from "lodash";
import {FormGroup, FormBuilder, Validators} from "@angular/forms";
import {SharedService} from "../../../core/services/shared-service.service";
import {ApiService} from "../../../core/http/api.service";

taskId: string;
updateTask: FormGroup;
currentTest:any = {};

 constructor(private _apiService: ApiService, private _formBuilder: FormBuilder, private _formControl: FormControl, private _sharedService: SharedService) {}

ngOnInit(): void {
this.categories = [
  {
    id: 1, name: "Category 1"
  },
  {
    id: 2, name: "Category 2"
  },
  {
    id: 3, name: "Category 3"
  }
];

 this.updateTask = this._formBuilder.group(this.formFields);

 this._apiService.getTaskInfo().subscribe(res => {
   this.Task = res;
   let formInfo = this.Task.info; 

   formInfo.forEach(function(task, index){
    console.log(task.key + ": " + task.data);
    this.updateTask .get(task.key).setValue(task.data);
   }, this)
 });

}

The array formInfo that contains task information looks like this:

[{
   "taskId":"5eb45c2738ae2549000ddb0a",
   "key":"title",
   "data":"Lorem ipsum dolor"
},
{
   "taskId":"5eb45c2738ae2549000ddb0a",
   "key":"short-description",
   "data":"Lorem ipsum dolor sit amet, consectetur adipisicing elit"
},
{
   "taskId":"5eb45c2738ae2549000ddb0a",
   "key":"full-description",
   "data":"Reprehenderit aperiam unde distinctio, fuga magnam asperiores laboriosam expedita fugiat numquam rerum debitis temporibus dolores."
}] 

Although the line

console.log(task.key + ": " + task.data)
outputs the correct values:

title: Lorem ipsum dolor
short-description: Lorem ipsum dolor sit amet, consectetur adipisicing elit
full-description: Reprehenderit aperiam unde distinctio, fuga magnam asperiores laboriosam expedita fugiat numquam rerum debitis temporibus dolores.

However, the form fields remain empty, leading to console errors such as:

Cannot find control with name: 'title'

This error persists for each object in the formInfo array.

What am I overlooking?


UPDATE:

I have made changes to the code responsible for populating the form:

currentTask: any = {};

constructor(private _apiService: ApiService, private _formBuilder: FormBuilder, private _formControl: FormControl, private _sharedService: SharedService) {}

updateTask = this._formBuilder.group({});

ngOnInit(): void {

    this._apiService.getTaskInfo().subscribe(res => {
        this.currentTask = res;
        let formInfo = this.currentTask.info;

        formInfo.forEach(function(item) {
            console.log(item.key + ": " + item.data);
            this.updateTest.addControl(item.key, this._formBuilder.control(item.data, Validators.required));
        }, this);
    });

}

A browser error

NullInjectorError: R3InjectorError(AppModule)[FormControl -> FormControl -> FormControl]: NullInjectorError: No provider for FormControl!
occurs.

Answer №1

When using formControlName attributes in your template, make sure you have FormControls inside your updateTask FormGroup.

If you encounter an issue with the get method trying to retrieve a non-existent FormControl :

this.updateTask.get(task.key).setValue(task.data);

A recommended approach is to instantiate a FormBuilder instance in your constructor to reduce boilerplate code:

constructor(private fb: FormBuilder){}

Create your FormGroup like this:

updateTask = this.fb.group({});

Note that typing the updateTask variable as a FormGroup does not create an instance of the FormGroup class:

updateTask: FormGroup;

Next, use a foreach loop to add all necessary FormControls:

formInfo.forEach((task) => {
  this.updateTask.addControl(task.key, this.fb.control(task.data))
})

By following these steps, you should be able to resolve any console errors. Additionally, here is a simplified and functional StackBlitz example to help guide you through the process : https://stackblitz.com/edit/stack-fromcontrols

Answer №2

Insert the code snippet below into your ngOnInit lifecycle hook:

this.taskForm = new FormGroup({
      title: new FormControl(),
      descriptionShort: new FormControl(),
      descriptionFull: new FormControl()
    });

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

Sending various values via a click in an HTML link

Hello, I am attempting to pass multiple values using the HTML onclick function. I am utilizing Javascript to generate a table dynamically. var user = element.UserName; var valuationId = element.ValuationId; $('#ValuationAssignedTable').append(&a ...

The issue of AFrame content failing to display on Google Chrome when used with hyperHTML

There seems to be an issue with A-Frame content not rendering on Chrome, despite working fine on FireFox and Safari. According to the demonstration on CodePen here, const { hyper, wire } = hyperHTML; class Box extends hyper.Component { render() { retu ...

Crafting a recursive Typescript Immutable.js Record through typing

I am currently working on representing a tree-like data structure using immutable js and typescript. At the moment, I am utilizing regular vanilla js objects to depict the nodes within the tree. Below is the type signature. type NodeType = { value: str ...

I require limitless onclick functionality, but unfortunately, transitions are not functioning as expected

I'm currently working on creating a dynamic photo gallery, but I've encountered a couple of issues that need to be addressed... The "onclick" function in my JavaScript only allows for a single click, whereas I need it to be able to handle mul ...

Code in JavaScript: Generating Random Number within a Loop

Can anyone help me come up with a unique JavaScript loop that can guess a correct number within the range of 1-500? I want each iteration of the loop to generate a new number that has not been guessed before, but it should guess in a random order. For ex ...

Encountering a challenge when attempting to upgrade to Angular 9: Issue with transitioning undecorated classes with DI migration

As I transition from Angular 8 to Angular 9, I encounter an error during the step related to transitioning undecorated classes with DI. While attempting to migrate, I faced an issue with undecorated classes that utilize dependency injection. Some project ...

Reset the select boxes when a button is clicked

I'm currently utilizing Devextreme within my Angular application, and I have three dx-selectbox elements in the component. I am attempting to clear all three dropdown selections when clicking a "clear" button. Unfortunately, I am unable to find a way ...

Breaking apart a combination of unions into a collective group of tuples within TypeScript

Looking for a solution similar to TypeScript extract union type from tuple, this question delves into how to split ['a' | 'b', number] into ['a', number] | ['b', number] rather than focusing on why they are not direc ...

The function in the method (in quasar) is not activated by the @change event

When I select an option, I am trying to retrieve the selected value in a function called within my methods. However, the function does not seem to be triggering. This is my code: From the template : <q-select filled v-model="invoice_product.tarri ...

Universal in Angular is malfunctioning

As a newcomer to Angular 4, I am looking to create an Angular app that is SEO friendly and supports Angular Universal (with the --universal flag after ung new or ung init). I have successfully created an Angular Universal app. However, when running the p ...

Is there a way to retrieve all IDs within an array of objects using a foreach loop and merge the data associated with each ID?

I am currently working on a TypeScript API where I have merged all the data from this API with some additional data obtained from another API function. I have provided a snippet of my code which adds data to the first index of an array. M ...

Exploring the world of jQuery sliders and dynamically updating div container content

Alright, here's what I have come up with so far: First, take a look at this website to see the idea I am trying to explain: What I am aiming for is this concept: A visitor goes to the provided website and wants to know what type of sandwich they can ...

Having trouble implementing pagination for news-api in Vue.js2?

I am currently working on implementing a basic pagination feature in my Vue component specifically for the newsapi.org API. While my initial API call in the created hook is functioning as expected, I am encountering difficulties navigating to different pa ...

Encountering issues with installing @vue/cli on Linux Ubuntu

Currently facing an issue while attempting to install the Vue CLI on Ubuntu (WSL). After running both yarn add global @vue/cli and npm install @vue/cli --global, it seems like the commands were successful. However, upon checking the version using vue --v ...

What could be causing Highchart to return the error message "Typeerror: undefined variable byte"?

My current project involves creating a graph using highchart and updating values every second. I am also working on displaying data in Mb, Kb, and Gb format on the graph by developing a function to convert byte values. Here is a snippet of my code: // hi ...

Struggling to compile Typescript with mocha using the Visual Studio Code Debugger

I'm currently troubleshooting unit testing using Visual Studio Code and mocha, but I encounter an error when mocha is launched. TSError: ⨯ Unable to compile TypeScript: mfa/test/index.test.ts(4,20): error TS2307: Cannot find module 'assert&ap ...

A guide on verifying a phone number using just one character

I am looking to validate a phone number with only one character being allowed. For example, the format should be XXX-XXXXXXX where "-" is the only allowed character. Below is my validation function: function validatePhoneNumber() { if(addform.staff_m ...

"Curious why the change event doesn't trigger when selecting an option that is already selected

Angular reactive forms are causing an issue where the change method for select field does not fire when selecting an already selected option. You can view an example of this behavior at the following link: https://stackblitz.com/edit/angular-2e1cvz. In t ...

Error: Unable to set value, val.set is not a defined function for this operation (Javascript

Encountering a problem while running the function val.set(key, value), resulting in a type error TypeError: val.set is not a function within the file vendor-es2015.js. Here's the simplified code snippet: import { Storage } from '@ionic/storage& ...

Firing a custom jQuery event when a page loaded via AJAX is complete, ensuring it is triggered

I am facing an issue with a particular scenario. There is a page that contains a script to load a child page and log a custom event, which is triggered in a Subform. --Index.html-- <body> <input type="button" class="clickable" value="Load child ...