5

I have built a dynamic form component in Angular 5 (based on documentation and example from https://angular.io/guide/dynamic-form).

Everything works find until I try and use angular material.

I have read a number of articles here on similar issues but they all seem to be because people were not importing correct modules or using mdInput or mat-Input instead of matInput. This is not the case for the problem I am experiencing.

Any thoughts or advice would be appreciated.

CHANGED CODE - BREAKS with ERROR -

*mat-form-field must contain a MatFormFieldControl.***

Dynamic Form Control Component Template

The only change I made to the working code below is to wrap the input field in and add the matInput attribute to the input field.

I am importing all the Material Modules (MatFormFieldModule and MatInputModule etc through a core module. All my material Inputs and Form Fields work in all other components in the application, so i don't believe the issues is that i am missing anything in the imports.

<div [formGroup]="form">

    <div [ngSwitch]="control.controlType">
        <mat-form-field>
            <input matInput placeholder="{{control.label}}" *ngSwitchCase="'textbox'" [formControlName]="control.key" [id]="control.key"
                [type]="control.type">
        </mat-form-field>
        <select [id]="control.label" *ngSwitchCase="'dropdown'" [formControlName]="control.key">
            <option value="">Select {{control.label}}</option>
            <option *ngFor="let opt of control.options" [value]="opt.key">{{opt.value}}</option>
        </select>
    </div>

    <div class="errorMessage" *ngIf="!isValid">{{control.label}} is required</div>
</div>

CURRENT CODE - This works perfectly but I am not getting the angular material formatting

Selector

<mi-dynamic-form [controls]="controls"></mi-dynamic-form>

Dynamic Form Component

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

import { DynamicFormBase } from './dynamic-form-base';

@Component({
    selector: 'mi-control',
    templateUrl: './dynamic-form-control.component.html'
})
export class DynamicFormControlComponent {

    // API
    @Input() control: DynamicFormBase<any>;
    @Input() form: FormGroup;

    get isValid() { return this.form.controls[this.control.key].valid; }
}

Dynamic Form Component Template

    <div [formGroup]="form">
    <div [ngSwitch]="control.controlType">
            <input  placeholder="{{control.label}}" *ngSwitchCase="'textbox'" [formControlName]="control.key" [id]="control.key"
                [type]="control.type">
        <select [id]="control.label" *ngSwitchCase="'dropdown'" [formControlName]="control.key">
            <option value="">Select {{control.label}}</option>
            <option *ngFor="let opt of control.options" [value]="opt.key">{{opt.value}}</option>
        </select>
    </div>

    <div class="errorMessage" *ngIf="!isValid">{{control.label}} is required</div>
</div>

Dynamic Form Control Component

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

import { DynamicFormBase } from './dynamic-form-base';

@Component({
    selector: 'mi-control',
    templateUrl: './dynamic-form-control.component.html'
})
export class DynamicFormControlComponent {

    // API
    @Input() control: DynamicFormBase<any>;
    @Input() form: FormGroup;

    get isValid() { return this.form.controls[this.control.key].valid; }
}

Dynamic Form Control Component Template

 <div [formGroup]="form">
        <!-- <label [attr.for]="control.key">{{control.label}}</label> -->

        <div [ngSwitch]="control.controlType">
            <mat-form-field>
                <input matInput placeholder="{{control.label}}" *ngSwitchCase="'textbox'" [formControlName]="key" [id]="control.key"
                    [type]="control.type">
            </mat-form-field>
            <mat-select [id]="control.label" *ngSwitchCase="'dropdown'" [formControlName]="control.key">
                <mat-option value="">Select {{control.label}}</mat-option>
                <mat-option *ngFor="let opt of control.options" [value]="opt.key">{{opt.value}}</mat-option>
            </mat-select>
        </div>

        <div class="errorMessage" *ngIf="!isValid">{{control.label}} is required</div>
    </div>
3
  • I think your <mat-select> must be surrounded by <mat-form-field> Commented Feb 8, 2018 at 9:13
  • Thanks for quick response, but i had that in originally and took it out as i was trying to rule out if it was an error with either one of them. Putting it back in still gives me the same error Commented Feb 8, 2018 at 9:34
  • I'm having the same issue, did you ever find a solution? Commented Nov 25, 2019 at 20:58

2 Answers 2

4

I was able to get this working with both Angular Dynamic Forms and Material. Check out working stackblitz example here showing both Dynamic Forms and use of Material.

Sign up to request clarification or add additional context in comments.

1 Comment

This was truly great for what I am doing right now
0

I am sure you had solved this problem. The error of mat-form-field must contain a MatFormFieldControl. means the material components used are not imported. i.e. MatButtonModule needs to be imported when using mat-button directive.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.