Issue with Angular 9 application: Unable to properly render form fields within a Material Design Dialog

I'm currently developing a "Tasks" application using Angular 9 and PHP. I've encountered an error that says

Cannot find control with name: <control name>
when attempting to pre-fill the update form with data.

Here is the form template:

<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 the component's .ts file:

task_hash: string;
currentTask: any = {};

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

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

ngOnInit(): void {

    this.task_hash = this._apiService.task_hash;

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

        formInfo.forEach(item => {
            if (item.key === 'title' || item.key === 'short-description' || item.key === 'description' || item.key === 'tags') {
                this.updateTask.addControl(item.key, this._formBuilder.control(item.data, item.key !== 'tags' ? Validators.required : null));
            };
        });
    });
}

The browser console shows an error message (for each form field):

Cannot find control with name: 'title'
.

The issue seems to stem from the fact that in another component, I open the form within an Angular Material Dialog triggered by a button click:

<button mat-button color="primary" (click)="openForm($event, task.task_hash)">Open</button>

In the trigger's .ts file

openEditForm(event, task_hash): void {

    event.stopPropagation();

    // Dialog Configuration
    const dialogConfig = new MatDialogConfig();
    dialogConfig.width = '60%';

    // Open Dialog
    this._matDialog.open(TaskFormComponent, dialogConfig);

    // Pass test_hash to API Service
    this.apiService.test_hash = test_hash;
}

To make the dialog work correctly, I also added this in the TaskModule:

entryComponents: [TestFormComponent];

It appears that the dialog opens before the form is populated, preventing the form from being filled. How can I resolve this issue?

Answer №1

In the template, there is no condition set to prevent the rendering of

<form [formGroup]="updateTask" name="edit_task_form">
until this._apiService.getTaskInfo() provides a response. This is why the error formControl not found occurs.

To solve this issue, you can add a flag inside the subscription of getTaskInfo().


this._apiService.getTaskInfo().subscribe(res => {
   ...
   this.formLoaded = true;
   ...
}

Then in the template, include:

<form *ngIf="formLoaded" [formGroup]="updateTask" name="edit_task_form">
   ...
   ...
</form>

You can find a demo code on stackblitz here (please disregard the html as it was copied from the original question).

Answer №2

Make sure to integrate the ngAfterViewInit interface in your component's class:

@Component
class AfterViewInitComponent implements AfterViewInit {

    ngAfterViewInit: void {
        this.task_hash = this._apiService.task_hash;

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

        formInfo.forEach(item => {
            if (item.key === 'title' || item.key === 'short-description' || item.key === 'description' || item.key === 'tags') {
                this.updateTask.addControl(item.key, this._formBuilder.control(item.data, item.key !== 'tags' ? Validators.required : null));
            };
        });
    });
 }

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

Are there any modules in Angular 8 that are used across various projects?

I am facing a challenge with managing two projects that share the same core functionality. These projects have identical layouts and pages, but certain components and modules are specific to each project. Currently, I maintain two separate Angular projects ...

Error message encountered during angular project build using ng build: angular.json file missing

I had successfully created a project on my laptop a month ago and didn't encounter any errors. However, when I cloned the repository to a new computer today, I encountered some issues. After running 'npm i' to install packages, I attempted t ...

Obtain an error response from a REST API by utilizing Angular 2

Client.service.ts: add(client: Client): Observable<Client> { return this.authHttp.post(this.URI, client) .map((res) => res.json() //...errors if any ,(message)=>message.json()); Client.add.componement.ts: this.clientS ...

Tips for resolving the error message "TypeError: Converting circular structure to JSON"

I had a straightforward query where I needed to select all from the aliases table. Everything was working fine until I ran npm update. TypeError: Converting circular structure to JSON public async fetchAliases(req: Request, res: Response): Promise< ...

Is it correct to implement an interface with a constructor in TypeScript using this method?

I am completely new to TypeScript (and JavaScript for the most part). I recently came across the article discussing the differences between the static and instance sides of classes in the TypeScript handbook. It suggested separating the constructor into an ...

Creating dynamic Angular child routes with variable initial segment

Recently, I've been working on a new project to set up a blogging system. The next step in my plan is to focus on the admin section, specifically editing posts. My idea for organizing the routes is as follows: /blog - Home page /blog/:slug - Access ...

The ngx-translate Angular translation file is being loaded twice unnecessarily

Upon reviewing the network tab in the browser's developer tools, I discovered that my Angular app translation file is being loaded twice. Is there an issue with this? Should it be loading multiple times? https://i.stack.imgur.com/vcKm1.png ...

The transition to CDK version 2 resulted in a failure of our test cases

After upgrading my CDK infrastructure code from version 1 to version 2, I encountered some failed test cases. The conversion itself was successful without any issues. The only changes made were updating the references from version 1 to version 2, nothing ...

Error: 'next' is not defined in the beforeRouteUpdate method

@Component({ mixins: [template], components: { Sidebar } }) export default class AppContentLayout extends Vue { @Prop({default: 'AppContent'}) title: string; @Watch('$route') beforeRouteUpdateHandler (to: Object, fro ...

Angular app encountering issues after trying to add new package

After making a clone of an existing Angular project, I successfully ran the application using ng serve. Upon wanting to add the SignalR package, I used the command: npm install @aspnet/signalr –-save The installation seemed to go smoothly at first. Howe ...

Creating an HTTP method handler function in Next.js API routes with an unspecified number of generic parameters

Looking to create a wrapper function in NextJS for API routes that can handle multiple HTTP methods with different handlers. For example, check out the TS playground interface GetResponse { hello: string, } // empty object type PostResponse = Record&l ...

In a Typescript Next Js project, the useReducer Hook cannot be utilized

I'm completely new to Typescript and currently attempting to implement the useReducer hook with Typescript. Below is the code I've written: import { useReducer, useContext, createContext } from "react" import type { ReactNode } from &q ...

Can I specify which modal or component will appear when I click on a component?

Working on a small Angular 5 project, I have a simple component that represents a food product shown below: [![enter image description here][1]][1] This component is nested within my main component. When this component is clicked, a quantity component/m ...

The componentWillReceiveProps method is not triggered when a property is removed from an object prop

Just starting out with React, so I could really use some assistance from the community! I am working with a prop called 'sampleProp' which is defined as follows: sampleProp = {key:0, value:[]} When I click a button, I am trying to remo ...

Searching with Mat-autocomplete across multiple fields simultaneously

I am struggling with a mat-autocomplete that contains 5000 objects, each consisting of a first name and a last name. My goal is to search for both the first name and last name simultaneously regardless of the input order. Currently, I can only search one ...

Dealing with 'TypeError X is Not a Function' Error in Angular (TypeScript): Occurrences in Certain Scenarios and Absence in Others

Recently, I came across an odd issue in Angular 14 where a type error kept popping up. Although I managed to refactor the code and find a workaround, I'm quite intrigued as to why this issue is happening so that I can prevent it from occurring again i ...

Creating a custom pipe that converts seconds to hours and minutes retrieved from an API can be achieved by implementing a transformation function

Can someone please provide guidance on creating a custom pipe in Angular 8 that converts seconds to hours and minutes? Thank you. <div class="col-2" *ngFor="let movie of moviesList"> <div class="movie"> {{ movie.attributes.title }} ...

How to efficiently import an external ES module from a URL using TypeScript

I've recently started experimenting with Observable notebooks and I must say, it's been a great experience so far. Now, my next goal is to integrate a notebook into my web app. The following vanilla JavaScript code using JavaScript modules accomp ...

How can I dynamically render a component using VueJS?

Incorporating a component named CanvasComp from my components folder, I am rendering it on the template like <CanvasComp :jsoData="data"/> to send jsonData to the component. However, I am seeking a way to dynamically render this component w ...

Exploring the Power of Map with Angular 6 HttpClient

My goal is to enhance my learning by fetching data from a mock JSON API and adding "hey" to all titles before returning an Observable. Currently, I am able to display the data without any issues if I don't use the Map operator. However, when I do use ...