Angular ng-content 不适用于 mat-form-field

我的目标:


我正在尝试构建一个带有清除按钮的可重复使用的 mat-form-field。


我如何尝试实现我的目标:


我创建了一个“mat-clearable-input”组件并像这样使用它:


<mat-clearable-input>

        <mat-label>Put a Number here pls</mat-label>

        <input matInput formControlName="number_form_control">

    </mat-clearable-input>

mat-clearable-input.component.html


<mat-form-field>

    <ng-content></ng-content>

</mat-form-field>

预期结果:


ng-content 标签获取标签和输入并将它们放入 mat-form-field 标签中。


实际结果:


Error: mat-form-field must contain a MatFormFieldControl.

    at getMatFormFieldMissingControlError (form-field.js:226)

    at MatFormField._validateControlChild (form-field.js:688)

    at MatFormField.ngAfterContentChecked (form-field.js:558)

    at callHook (core.js:2926)

    at callHooks (core.js:2892)

    at executeInitAndCheckHooks (core.js:2844)

    at refreshView (core.js:7239)

    at refreshComponent (core.js:8335)

    at refreshChildComponents (core.js:6991)

    at refreshView (core.js:7248)

看起来我遗漏了一些东西而且我没有正确使用 ng-content 标签。


我无法在 angular 网站上找到 ng-content 标签的文档。


感谢您的任何帮助。


在下面回答后编辑


所以我尝试了这个建议的方法:


export class MatClearableInputComponent implements OnInit {

  @ContentChild(MatFormFieldControl) _control: MatFormFieldControl<any>;

  @ViewChild(MatFormField) _matFormField: MatFormField;

  // see https://stackoverflow.com/questions/63898533/angular-ng-content-not-working-with-mat-form-field/

  ngOnInit() {

    this._matFormField._control = this._control;

  }


}

不幸的是,当我尝试在表单中使用它时,它仍然失败并出现错误“错误:mat-form-field 必须包含 MatFormFieldControl”。


我尝试以某种形式使用此组件的代码:


<mat-clearable-input>

    <mat-label>Numero incarico</mat-label>

    <buffered-input matInput formControlName="numero"></buffered-input>

</mat-clearable-input>

在 stackblitz 上重现:https://stackblitz.com/edit/angular-material-starter-xypjc5 ?file=app/clearable-form-field/clearable-form-field.component.html


请注意 mat-form-field 功能如何不起作用(没有轮廓,没有浮动标签),同时打开控制台,您将看到错误错误:mat-form-field 必须包含 MatFormFieldControl。


选项 2 发布后编辑


我试过这样做:


<mat-form-field>

  <input matInput hidden>

  <ng-content></ng-content>

</mat-form-field>

它有效,但是当我在我的表单字段中添加一个 mat-label 时,如下所示:


      

大话西游666
浏览 91回答 3
3回答

繁星点点滴滴

另一种解决方案是使用指令来实现行为。import {&nbsp; AfterViewInit,&nbsp; Component,&nbsp; ComponentFactory,&nbsp; ComponentFactoryResolver,&nbsp; ContentChild,&nbsp; Directive,&nbsp; Injector,&nbsp; Input,&nbsp; Optional,&nbsp; SkipSelf,&nbsp; TemplateRef,&nbsp; ViewContainerRef,} from '@angular/core';import { MatFormFieldControl } from '@angular/material/form-field';@Directive({&nbsp; selector: '[appClearable]'})export class ClearableDirective implements AfterViewInit {&nbsp; @ContentChild(MatFormFieldControl) matInput: MatFormFieldControl<any>;&nbsp; @Input() appClearable: TemplateRef<any>;&nbsp; private factory: ComponentFactory<ClearButtonComponent>;&nbsp; constructor(&nbsp; &nbsp; private vcr: ViewContainerRef,&nbsp; &nbsp; resolver: ComponentFactoryResolver,&nbsp; &nbsp; private injector: Injector,&nbsp; ) {&nbsp; &nbsp; this.factory = resolver.resolveComponentFactory(ClearButtonComponent);&nbsp; }&nbsp; ngAfterViewInit(): void {&nbsp; &nbsp; if (this.appClearable) {&nbsp; &nbsp; &nbsp; this.vcr.createEmbeddedView(this.appClearable);&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; this.vcr.createComponent(this.factory, undefined, this.injector);&nbsp; &nbsp; }&nbsp; }&nbsp; /**&nbsp; &nbsp;* This is used to clear the formControl oder HTMLInputElement&nbsp; &nbsp;*/&nbsp; clear(): void {&nbsp; &nbsp; if (this.matInput.ngControl) {&nbsp; &nbsp; &nbsp; this.matInput.ngControl.control.reset();&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; this.matInput.value = '';&nbsp; &nbsp; }&nbsp; }}/**&nbsp;* This is the markup/component for the clear-button that is shown to the user.&nbsp;*/@Component({&nbsp; selector: 'app-clear-button',&nbsp; template: `&nbsp; <button (click)="clearHost()">Clear</button>&nbsp; `})export class ClearButtonComponent {&nbsp; constructor(@Optional() @SkipSelf() private clearDirective: ClearableDirective) { }&nbsp; clearHost(): void {&nbsp; &nbsp; if (this.clearDirective) {&nbsp; &nbsp; &nbsp; this.clearDirective.clear();&nbsp; &nbsp; }&nbsp; }}这会appClearable为后备布局创建一个名为的指令和一个可选的组件。确保将组件和指令添加到declarations模块的 -array 中。您可以指定用于提供用户界面的模板,也可以将其ClearButtonComponent用作通用的解决方案。标记如下所示:<!-- Use it with a template reference --><mat-form-field [appClearable]="clearableTmpl">&nbsp; <input type="text" matInput [formControl]="exampleInput"></mat-form-field><!-- use it without a template reference --><mat-form-field appClearable>&nbsp; <input type="text" matInput [formControl]="exampleInput2"></mat-form-field><ng-template #clearableTmpl>&nbsp; <button (click)="exampleInput.reset()">Marked-Up reference template</button></ng-template>无论是否使用 ngControl/FormControl,这都适用,但您可能需要根据您的用例对其进行调整。

红颜莎娜

从 2022 年的 Angular 14 开始,MatFormField 的问题已经针对angular/angular#37319关闭,没有解决方案。如果您需要它工作,以下似乎是现在可以使用<ng-content>with的最佳解决方案mat-form-field:@Component({&nbsp; selector: 'my-input-wrapper',&nbsp; template: `&nbsp; &nbsp; <mat-form-field appearance="standard">&nbsp; &nbsp; &nbsp; <ng-content></ng-content>&nbsp; &nbsp; &nbsp; <!-- make sure this is destroyed so all bindings/subscriptions are removed-->&nbsp; &nbsp; &nbsp; <input *ngIf="isBeforeViewInit$$ | async" hidden matInput />&nbsp; &nbsp; </mat-form-field>&nbsp; `,});class MyInputWrapper implement AfterViewInit {&nbsp; isBeforeViewInit$$ = new BehaviorSubject(true);&nbsp; @ContentChild(MatFormFieldControl) matFormControl: MatFormFieldControl<unknown>;&nbsp; @ViewChild(MatFormField) matFormField: MatFormField;&nbsp; ngAfterViewInit() {&nbsp; &nbsp; // replace the reference to the dummy control&nbsp; &nbsp; this.matFormField._control = this.matFormControl;&nbsp; &nbsp; // force the form field to rebind everything to the actual control&nbsp; &nbsp; this.matFormField.ngAfterContentInit();&nbsp; &nbsp; this.isBeforeViewInit$$.next(false);&nbsp; }}

千万里不及你

更新:选项 1 不适用于新的角度版本,因为在钩子@ViewChild()中返回未定义。ngOnInit()另一个技巧是使用假人MatFormFieldControl-选项 2<mat-form-field>&nbsp; <input matInput hidden>&nbsp; <ng-content></ng-content></mat-form-field>编辑:抛出该错误是因为MatFormField组件查询使用的子内容@ContentChild(MatFormFieldControl)如果您使用嵌套则不起作用ng-content(MatFormField 也使用内容投影)。选项 1(已弃用)以下是如何让它工作 -@Component({&nbsp; selector: 'mat-clearable-input',&nbsp; template: `&nbsp; &nbsp; <mat-form-field>&nbsp; &nbsp; &nbsp; <ng-content></ng-content>&nbsp; &nbsp; </mat-form-field>&nbsp; `})export class FieldComponent implements OnInit {&nbsp;&nbsp; &nbsp; @ContentChild(MatFormFieldControl) _control: MatFormFieldControl<any>;&nbsp; &nbsp; @ViewChild(MatFormField) _matFormField: MatFormField;&nbsp; &nbsp; ngOnInit() {&nbsp; &nbsp; &nbsp; &nbsp; this._matFormField._control = this._control;&nbsp; &nbsp; }}请检查这个 stackBlitz。此外,已经创建了这个问题github。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript