我们正试图在我们公司建立我们自己的形式场组件。我们试图这样包装材料设计的组件:
字段:
<mat-form-field>
<ng-content></ng-content>
<mat-hint align="start"><strong>{{hint}}</strong> </mat-hint>
<mat-hint align="end">{{message.value.length}} / 256</mat-hint>
<mat-error>This field is required</mat-error>
</mat-form-field>
文本框:
<field hint="hint">
<input matInput
[placeholder]="placeholder"
[value]="value"
(change)="onChange($event)"
(keydown)="onKeydown($event)"
(keyup)="onKeyup($event)"
(keypress)="onKeypress($event)">
</field>
用法:
<textbox value="test" hint="my hint"></textbox>
结果大致如下:
<textbox placeholder="Personnummer/samordningsnummer" value="" ng-reflect-placeholder="Personnummer/samordningsnummer">
<field>
<mat-form-field class="mat-input-container mat-form-field">
<div class="mat-input-wrapper mat-form-field-wrapper">
<div class="mat-input-flex mat-form-field-flex">
<div class="mat-input-infix mat-form-field-infix">
<input _ngcontent-c4="" class="mat-input-element mat-form-field-autofill-control" matinput="" ng-reflect-placeholder="Personnummer/samordningsnummer" ng-reflect-value="" id="mat-input-2" placeholder="Personnummer/samordningsnummer" aria-invalid="false">
<span class="mat-input-placeholder-wrapper mat-form-field-placeholder-wrapper"></span>
</div>
</div>
<div class="mat-input-underline mat-form-field-underline">
<span class="mat-input-ripple mat-form-field-ripple"></span>
</div>
<div class="mat-input-subscript-wrapper mat-form-field-subscript-wrapper"></div>
</div>
</mat-form-field>
</field>
</textbox>
但是我在控制台得到“mat-form-field必须包含MatFormFieldControl”。我猜这与mat-form-field不直接包含matinput字段有关。但它包含了它,只是在ng-content投影中。
以下是闪电战:
https://stackblitz.com/edit/angular-xpvwzf
如果上面所有主要的代码结构/配置答案都不能解决您的问题,那么还有一件事需要检查:确保您没有以某种方式使<input>标记失效。
例如,我收到了相同的mat-form-field必须包含一个MatFormFieldControl错误消息,在意外地将一个必需的属性放在自关闭斜杠/之后,这有效地使我的<input/>无效。换句话说,我这样做了(参见输入标签属性的末尾):
错误的:
<input matInput type="text" name="linkUrl" [formControl]="listingForm.controls['linkUrl']" /required>
正确的:
<input matInput type="text" name="linkUrl" [formControl]="listingForm.controls['linkUrl']" required/>
如果你犯了这个错误或其他使你的<input>无效的错误,那么你可以得到mat-form-field必须包含一个MatFormFieldControl错误。不管怎样,这只是调试时要注意的另一件事。
如果上面所有主要的代码结构/配置答案都不能解决您的问题,那么还有一件事需要检查:确保您没有以某种方式使<input>标记失效。
例如,我收到了相同的mat-form-field必须包含一个MatFormFieldControl错误消息,在意外地将一个必需的属性放在自关闭斜杠/之后,这有效地使我的<input/>无效。换句话说,我这样做了(参见输入标签属性的末尾):
错误的:
<input matInput type="text" name="linkUrl" [formControl]="listingForm.controls['linkUrl']" /required>
正确的:
<input matInput type="text" name="linkUrl" [formControl]="listingForm.controls['linkUrl']" required/>
如果你犯了这个错误或其他使你的<input>无效的错误,那么你可以得到mat-form-field必须包含一个MatFormFieldControl错误。不管怎样,这只是调试时要注意的另一件事。
部分解决方案是将材料表单字段包装在自定义组件中,并在其上实现ControlValueAccessor接口。除了内容投影之外,效果几乎是一样的。
参见Stackblitz的完整示例。
我在CustomInputComponent中使用了FormControl(响应式表单),但如果你需要更复杂的表单元素,FormGroup或FormArray也应该工作。
app.component.html
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<mat-form-field appearance="outline" floatLabel="always" color="primary">
<mat-label>First name</mat-label>
<input matInput placeholder="First name" formControlName="firstName" required>
<mat-hint>Fill in first name.</mat-hint>
<mat-error *ngIf="firstNameControl.invalid && (firstNameControl.dirty || firstNameControl.touched)">
<span *ngIf="firstNameControl.hasError('required')">
You must fill in the first name.
</span>
</mat-error>
</mat-form-field>
<custom-input
formControlName="lastName"
[errorMessages]="errorMessagesForCustomInput"
[hint]="'Fill in last name.'"
[label]="'Last name'"
[isRequired]="true"
[placeholder]="'Last name'"
[validators]="validatorsForCustomInput">
</custom-input>
<button mat-flat-button
color="primary"
type="submit"
[disabled]="form.invalid || form.pending">
Submit
</button>
</form>
custom-input.component.html
<mat-form-field appearance="outline" floatLabel="always" color="primary">
<mat-label>{{ label }}</mat-label>
<input
matInput
[placeholder]="placeholder"
[required]="isRequired"
[formControl]="customControl"
(blur)="onTouched()"
(input)="onChange($event.target.value)">
<mat-hint>{{ hint }}</mat-hint>
<mat-error *ngIf="customControl.invalid && (customControl.dirty || customControl.touched)">
<ng-container *ngFor="let error of errorMessages">
<span *ngFor="let item of error | keyvalue">
<span *ngIf="customControl.hasError(item.key)">
{{ item.value }}
</span>
</span>
</ng-container>
</mat-error>
</mat-form-field>