Angular:mat-form-field 必须包含一个 MatFormFieldControl
Posted
技术标签:
【中文标题】Angular:mat-form-field 必须包含一个 MatFormFieldControl【英文标题】:Angular: mat-form-field must contain a MatFormFieldControl 【发布时间】:2019-05-24 22:40:41 【问题描述】:我正在尝试添加带有自定义电话号码输入控件的表单字段。我以https://material.angular.io/components/form-field/examples的手机为例。
代码如下:
<mat-form-field>
<example-tel-input placeholder="Phone number" required></example-tel-input>
<mat-icon matSuffix>phone</mat-icon>
<mat-hint>Include area code</mat-hint>
</mat-form-field>
import FocusMonitor from '@angular/cdk/a11y';
import coerceBooleanProperty from '@angular/cdk/coercion';
import Component, ElementRef, Input, OnDestroy from '@angular/core';
import FormBuilder, FormGroup from '@angular/forms';
import MatFormFieldControl from '@angular/material';
import Subject from 'rxjs';
/** @title Form field with custom telephone number input control. */
@Component(
selector: 'form-field-custom-control-example',
templateUrl: 'form-field-custom-control-example.html',
styleUrls: ['form-field-custom-control-example.css'],
)
export class FormFieldCustomControlExample
/** Data structure for holding telephone number. */
export class MyTel
constructor(public area: string, public exchange: string, public subscriber: string)
/** Custom `MatFormFieldControl` for telephone number input. */
@Component(
selector: 'example-tel-input',
templateUrl: 'example-tel-input-example.html',
styleUrls: ['example-tel-input-example.css'],
providers: [provide: MatFormFieldControl, useExisting: MyTelInput],
host:
'[class.example-floating]': 'shouldLabelFloat',
'[id]': 'id',
'[attr.aria-describedby]': 'describedBy',
)
export class MyTelInput implements MatFormFieldControl<MyTel>, OnDestroy
static nextId = 0;
parts: FormGroup;
stateChanges = new Subject<void>();
focused = false;
ngControl = null;
errorState = false;
controlType = 'example-tel-input';
id = `example-tel-input-$MyTelInput.nextId++`;
describedBy = '';
get empty()
const value: area, exchange, subscriber = this.parts;
return !area && !exchange && !subscriber;
get shouldLabelFloat() return this.focused || !this.empty;
@Input()
get placeholder(): string return this._placeholder;
set placeholder(value: string)
this._placeholder = value;
this.stateChanges.next();
private _placeholder: string;
@Input()
get required(): boolean return this._required;
set required(value: boolean)
this._required = coerceBooleanProperty(value);
this.stateChanges.next();
private _required = false;
@Input()
get disabled(): boolean return this._disabled;
set disabled(value: boolean)
this._disabled = coerceBooleanProperty(value);
this.stateChanges.next();
private _disabled = false;
@Input()
get value(): MyTel | null
const value: area, exchange, subscriber = this.parts;
if (area.length === 3 && exchange.length === 3 && subscriber.length === 4)
return new MyTel(area, exchange, subscriber);
return null;
set value(tel: MyTel | null)
const area, exchange, subscriber = tel || new MyTel('', '', '');
this.parts.setValue(area, exchange, subscriber);
this.stateChanges.next();
constructor(fb: FormBuilder, private fm: FocusMonitor, private elRef: ElementRef<HTMLElement>)
this.parts = fb.group(
area: '',
exchange: '',
subscriber: '',
);
fm.monitor(elRef, true).subscribe(origin =>
this.focused = !!origin;
this.stateChanges.next();
);
ngOnDestroy()
this.stateChanges.complete();
this.fm.stopMonitoring(this.elRef);
setDescribedByIds(ids: string[])
this.describedBy = ids.join(' ');
onContainerClick(event: MouseEvent)
if ((event.target as Element).tagName.toLowerCase() != 'input')
this.elRef.nativeElement.querySelector('input')!.focus();
example-tel-input-example.html
<div [formGroup]="parts" class="example-tel-input-container">
<input class="example-tel-input-element" formControlName="area" size="3">
<span class="example-tel-input-spacer">–</span>
<input class="example-tel-input-element" formControlName="exchange" size="3">
<span class="example-tel-input-spacer">–</span>
<input class="example-tel-input-element" formControlName="subscriber" size="4">
</div>
但我收到以下错误:
错误错误:mat-form-field 必须包含 MatFormFieldControl。
【问题讨论】:
请确保 MatInputModule 已导入。 github.com/angular/material2/issues/7898 @KimwanOgot 您的解决方案已为我解决。谢谢 【参考方案1】:需要import
两个模块并在导入和导出部分添加。
import MatFormFieldModule from '@angular/material/form-field';
import MatInputModule from '@angular/material/input';
@NgModule (
imports: [ MatFormFieldModule, MatInputModule ],
exports: [ MatFormFieldModule, MatInputModule ]
)
最让大家怀念的是'/'
这个角色。如果您看到 Angular Material Documentation ,他们也会错过这个(上次检查时间为 2020 年 6 月 16 日,甚至不知道他们是否更新了)。我举个例子说明一下
<!-- Wrong -->
<mat-form-field>
<input matInput>
</mat-form-field>
<!-- Right -->
<mat-form-field>
<input matInput />
</mat-form-field>
仔细查看sn-p。当<input
开始时,它必须以/>
结尾,但大多数人会错过/
(反斜杠)字符。
【讨论】:
哦,哇,非常感谢,直接从页面上复制了他们的示例,但无法正常工作!【参考方案2】:确保 MatInputModule 已导入,并且 <mat-form-field>
包含 <input>
和 matInput / matSelect
指令。
https://github.com/angular/material2/issues/7898
【讨论】:
【参考方案3】:导入MatInputModule
,解决了我的错误
【讨论】:
【参考方案4】:你需要将你的类指定为MatFormFieldControl
的提供者
https://material.angular.io/guide/creating-a-custom-form-field-control#providing-our-component-as-a-matformfieldcontrol
@Component(
selector: 'form-field-custom-control-example',
templateUrl: 'form-field-custom-control-example.html',
styleUrls: ['form-field-custom-control-example.css'],
providers: [
provide: MatFormFieldControl, useExisting: FormFieldCustomControlExample
]
)
【讨论】:
【参考方案5】:另外,别忘了在输入标签中写上name属性:
name="yourName"
【讨论】:
【参考方案6】:关闭输入标签的另一个可能问题。如果您从 Angular 示例之一 (https://material.angular.io/components/datepicker/overview) 复制代码,您最终可能会得到以下代码:
<mat-form-field appearance="fill">
<mat-label>Choose a date</mat-label>
<input matInput [matDatepicker]="picker">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
输入应该有结束标记(斜杠):
<input matInput [matDatepicker]="picker" />
【讨论】:
【参考方案7】:如果您在代码中使用任何“输入”标签和“mat-form-field”,请确保在输入标签中包含“matInput”
如果'mat-form-field'的子标签中存在任何*ngIf,则在'mat-form-field'标签中指定*ngIf条件
【讨论】:
谢谢,很有帮助【参考方案8】:这将解决您的问题
import
MatFormFieldModule,
MatInputModule
from "@angular/material";
【讨论】:
【参考方案9】:错误提示mat-form-field
应至少包含一个从中获取输入的表单字段。
例如:matInput
mat-select
等
在您的情况下,您可以在 example-tel-input-example.html 中的输入字段中添加 matInput
标签。您还可以将mat-form-field
移动到example-tel-input-example
组件中,并将其添加到每个matInput
字段中。
<div [formGroup]="parts" class="example-tel-input-container">
<mat-form-field>
<input matInput class="example-tel-input-element" formControlName="area" size="3">
</mat-form-field>
<span class="example-tel-input-spacer">–</span>
<mat-form-field>
<input matInput class="example-tel-input-element" formControlName="exchange" size="3">
</mat-form-field>
<span class="example-tel-input-spacer">–</span>
<mat-form-field>
<input matInput class="example-tel-input-element" formControlName="subscriber" size="4">
</mat-form-field>
</div>
注意:mat-icon
或 mat-hint
不能被视为表单域
【讨论】:
以上是关于Angular:mat-form-field 必须包含一个 MatFormFieldControl的主要内容,如果未能解决你的问题,请参考以下文章
浏览器控制台中的错误 mat-form-field 必须包含 MatFormFieldControl
Angular 4 mat-form-field with mat-select
ERROR 错误:使用 API 文档时,mat-form-field 必须包含 MatFormFieldControl?
Angular 8:将 Mat-form-field 中的高度更改为特定像素数