0

I am looking for some help on trying to clear up, this all to common error. I am using forms in two different parts of my application, and the form works perfectly in one part, but not the other. I have imported both ReactiveFormsModule and FormsModule.

resolution.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { ResolutionRoutingModule } from './resolution-routing.module';
import { ResolutionComponent } from './resolution/resolution.component';
import { ResolutionDetailComponent } from './resolution-detail/resolution-detail.component';
import { ResolutionListComponent } from './resolution-list/resolution-list.component';
import { NewResolutionComponent } from '../../forms/new-resolution/new-resolution.component';
import { MatFormFieldModule } from '@angular/material/form-field';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatDialogModule } from '@angular/material/dialog';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { MatCardModule } from '@angular/material/card';
import { ResolutionEditComponent } from '../../forms/resolution-edit/resolution-edit.component';


@NgModule({
  declarations: [ResolutionComponent,
ResolutionDetailComponent,
ResolutionListComponent,
NewResolutionComponent,
ResolutionEditComponent],
  imports: [
    CommonModule,
    ResolutionRoutingModule,
    MatFormFieldModule,
    ReactiveFormsModule,
    MatDialogModule,
    FormsModule,
    MatInputModule,
    MatSelectModule,
    MatCardModule
  ]
})
export class ResolutionModule { }

In the component NewResolutionComponent my form works as expected, and I get no errors.

new-resolution-component.html(snippet: I only included one input function)

<form (ngSubmit)='onSubmit()'[formGroup]='ResolutionFormGroup'>
<mat-form-field>
        <mat-label>Title</mat-label>
        <input [formControl]='TitleControl' matInput placeholder="Title" required/>
</mat-form-field>
....
</form>

new-resolution.component.ts

import { Component, OnInit } from '@angular/core';
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
import { MatDialogRef } from '@angular/material/dialog';
import { AuthService } from '../../shared/services/auth.service';
import { ResolutionsService } from '../../shared/services/resolutions.service';

@Component({
  selector: 'app-new-resolution',
  templateUrl: './new-resolution.component.html',
  styleUrls: ['./new-resolution.component.scss']
})
export class NewResolutionComponent implements OnInit {
  uid: string
  category_id: string
  title: string
  description: string
  catId: string
  categoryList = []

  TitleControl: AbstractControl
  DescriptionControl: AbstractControl
  UserIdControl: AbstractControl
  CategoryControl: AbstractControl
  ResolutionFormGroup: FormGroup

  constructor(public as: AuthService,
    public rs: ResolutionsService,
    public dialog: MatDialogRef<NewResolutionComponent>) { }

    userid: string
    
  ngOnInit(): void {
    this.ResInit()
  }
  private ResInit() {
    this.ResolutionFormGroup = new FormGroup({})
    this.ResolutionFormGroup.registerControl('id',(this.UserIdControl = new FormControl('this',[Validators.required])))
    this.ResolutionFormGroup.registerControl('category_id',(this.CategoryControl = new FormControl('',[Validators.required])))
    this.ResolutionFormGroup.registerControl('title',(this.TitleControl = new FormControl('SUPER',[Validators.required])))
    this.ResolutionFormGroup.registerControl('description',(this.DescriptionControl = new FormControl('',[Validators.required])))
  }

This produces the desired output where my input has a placeholder of 'SUPER'. However, when I try to recreate this in another file, I get an entirely different result, and errors.

resolution-edit.component.html(snippet: only showing one input as the others are identical)

<form formGroup='ResEditGroup'>
    <mat-form-field>
        <mat-label>Title</mat-label>
        <input [FormControl]='TitleControl' matInput placeholder="Title" required/>
    </mat-form-field>

The first thing I notice is that around my FormControl I have '[]'. If I remove the brackets, my code will run without giving the error: Can't bind to 'FormControl' since it isn't a known property of 'input'.

resolution-edit.component.ts

import { Component, Inject, OnInit } from '@angular/core';
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';

@Component({
  selector: 'app-resolution-edit',
  templateUrl: './resolution-edit.component.html',
  styleUrls: ['./resolution-edit.component.scss']
})
export class ResolutionEditComponent implements OnInit {
  ResEditGroup: FormGroup
  TitleControl: AbstractControl
  DescriptionControl: AbstractControl

  description: string
  title: string

  descriptionInput: string
  titleInput: string
  constructor(
    // @Inject(MAT_DIALOG_DATA) data
    ) {
    // this.descriptionInput = data.description
    // this.titleInput = data.title
   }

  ngOnInit(): void {
    this.EditInit()
  }
  EditInit(): void{
    this.ResEditGroup = new FormGroup({})
    this.ResEditGroup.registerControl('title',(this.TitleControl = new FormControl('SUPERBAD',[Validators.required])))  
    this.ResEditGroup.registerControl('description',(this.DescriptionControl = new FormControl('',[Validators.required])))
  }

}

Based on the comparison of both of my components, I would expect the input of the second component to display a placeholder of 'SUPERBAD', just as I had a placeholder of 'SUPER' in the first. However, in this case, I get no placeholder, except for what I declare directly inside the HTML input.
How do I get my second component to display 'SUPERBAD'?

Paul Carlson
  • 379
  • 5
  • 18
  • Does this answer your question? [Can't bind to 'formControl' since it isn't a known property of 'input' - Angular2 Material Autocomplete issue](https://stackoverflow.com/questions/43220348/cant-bind-to-formcontrol-since-it-isnt-a-known-property-of-input-angular) – Giannis Jan 21 '21 at 14:59
  • That does not, in that answer they are talking about importing `ReactiveFormsModule` and applying it to the components. My `resolution.module.ts` has it imported and declares both of my components. – Paul Carlson Jan 21 '21 at 15:10
  • @PaulCarlson, `[formControl]` need a FormControl variable, see that is `[formControl]="control"` where control is some like `control=newFormControl()` or you has a getter `get control(){return this.myForm.get('control')}`. `formControlName="string"` has no `[` `]` and is a "string". Some times you'll see [formControlName]="variable", but this "variable" is a string. – Eliseo Jan 21 '21 at 16:36

1 Answers1

1

Before we try to answer what is wrong with the code, lets try to refactor it to a shorter code.

import { Component, Inject, OnInit } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';

**resolution-edit.component.ts**

@Component({
  selector: 'app-resolution-edit',
  templateUrl: './resolution-edit.component.html',
  styleUrls: ['./resolution-edit.component.scss']
})
export class ResolutionEditComponent implements OnInit {
  resEditGroup = this.fb.group({
     title: ['SUPERBAD', [Validators.required]],
     description: ['', [Validators.required]]
  })
  constructor(
    private fb: FormBuilder,
    // @Inject(MAT_DIALOG_DATA) data
    ) {
    // this.descriptionInput = data.description
    // this.titleInput = data.title
   }

  ngOnInit(): void {
  }

}

With the above you can have resolution-edit.component.html

<form [formGroup]='ResEditGroup'>
    <mat-form-field>
        <mat-label>Title</mat-label>
        <input formControlName='title' matInput placeholder="Title" required/>
    </mat-form-field>

Below are the changes I have made.

  1. I am using a FormBuilder to generate my FormGroup. With this I dont need to create a new FormFroup and FormControl using new
  2. Changed to camelCase
  3. important I am binding to the FormGroup using [] and for the controls I am passing formControlName as a string. This is actually where you have a problem for you are passing in a FormGroup but not binding to ResEditGroup
Owen Kelvin
  • 14,054
  • 10
  • 41
  • 74