我们正试图在我们公司建立我们自己的形式场组件。我们试图这样包装材料设计的组件:

字段:

<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


当前回答

我不小心从输入字段中删除了matInput指令,这导致了同样的错误。

eg.

<mat-form-field>
   <input [readOnly]="readOnly" name="amount" formControlName="amount" placeholder="Amount">
</mat-form-field>

固定的代码

 <mat-form-field>
   <input matInput [readOnly]="readOnly" name="amount" formControlName="amount" placeholder="Amount">
</mat-form-field>

其他回答

部分解决方案是将材料表单字段包装在自定义组件中,并在其上实现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>

如果上面所有主要的代码结构/配置答案都不能解决您的问题,那么还有一件事需要检查:确保您没有以某种方式使<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错误。不管怎样,这只是调试时要注意的另一件事。

在我的例子中,输入元素上漏掉了“onChanges()”的一个右括号,因此输入元素显然根本没有被呈现:

<input mat-menu-item 
      matInput type="text" 
      [formControl]="myFormControl"
      (ngModelChange)="onChanged()>

对我来说,错误是由于在<mat-form-field></mat-form-field>中缺少<input>和formControl属性

<form [formGroup]="FormName">
    <mat-form-field>
    <mat-label>Name</mat-label>
    </mat-form-field>
</form>

哪个是错误的… 正确的如下所示

<form [formGroup]="FormName">
    <mat-form-field>
    <mat-label>Name</mat-label>
    <input matInput formControlName="name">
    </mat-form-field>
</form>

在你的模块中导入MatInputModule。Ts文件,它将解决问题。

import { MatInputModule } from '@angular/material/input';

后面的表述是原来的答案。

不幸的是,目前还不支持将内容投影到mat-form-field。 请跟踪以下github问题,以获得有关它的最新消息。

到目前为止,唯一的解决方案是将您的内容直接放入mat-form-field组件或实现MatFormFieldControl类,从而创建一个自定义的表单字段组件。