gpt4 book ai didi

angular - 如何编写 Angular Material 表单控件组件

转载 作者:太空狗 更新时间:2023-10-29 16:56:37 25 4
gpt4 key购买 nike

下面的代码显示了一个允许选择美国州的自动完成表单控件。

  <mat-form-field class="example-full-width">
<input matInput placeholder="State" aria-label="State" [matAutocomplete]="auto" [formControl]="stateCtrl">
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let state of filteredStates | async" [value]="state.name">
<img style="vertical-align:middle;" aria-hidden src="{{state.flag}}" height="25" />
<span>{{ state.name }}</span> |
<small>Population: {{state.population}}</small>
</mat-option>
</mat-autocomplete>
</mat-form-field>

但是,如果在我的应用程序中有许多位置需要这种类型的输入,那么将其转换为一个组件(指令?)是有意义的,所有样板文件都不需要重复。但是,我仍然希望能够以模板驱动或模型驱动的形式使用它,并允许容器组件改变占位符、验证等。

实现此目标的简单而可靠的方法是什么?

我尝试过为 Angular 推荐的一般方法,但它们没有考虑 Angular Material 的各种要求。例如。需要实现 MatFormFieldControl。 Angular Material 提供的指南更多地针对使用原始元素创建新的表单控件,而不是利用/包装现有的 Angular Material 表单控件。

目标是能够以一种形式做这样的事情:

<mat-form-field>
<lookup-state placeholder="State of Residence" required="true" formControlName="resState">
</lookup-state>
</mat-form-field>

最佳答案

我将使用 Angular Material 粘贴我的组件示例。我创建了一个自定义输入组件(两种情况:简单输入或自动完成):

这是我的Input.component.html

<mat-form-field color="accent" [hideRequiredMarker]="true" [class.mat-form-field-invalid]="hasErrors">
<ng-container *ngIf="autocomplete">
<input matInput [matAutocomplete]="auto" [type]="type" [placeholder]="placeholder" [disabled]="isDisabled" [value]="innerValue" (input)="autocompleteHandler($event)" (blur)="autocompleteBlur($event)">
<mat-autocomplete #auto [displayWith]="displayText" (optionSelected)="updateOption($event)">
<mat-option *ngFor="let choice of autocompleteChoices | async" [value]="choice">{{ choice.text }}</mat-option>
</mat-autocomplete>
</ng-container>
<input *ngIf="!autocomplete" matInput [type]="type" [placeholder]="placeholder" [disabled]="isDisabled" [value]="innerValue" (input)="inputHandler($event)" (blur)="setTouched()">
</mat-form-field>

这是我的Input.component.ts

import { Component, Input, forwardRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor, NgModel } from '@angular/forms';
import { MatAutocompleteSelectedEvent } from '@angular/material';

import { ChoiceList } from '../../../../models/choice-list';
import { ChoiceSource } from '../../../../models/choice-source';
import { getFlagAttribute } from '../../../../utils';
import { HintComponent } from '../hint/hint.component';
import { ErrorsComponent } from '../errors/errors.component';
import { FormField } from '../form-field';
import { ChoiceModel } from '../../../../models/choice-model';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/toPromise';

@Component({
selector: 'my-input',
templateUrl: './input.component.html',
styleUrls: ['./input.component.scss'],
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => InputComponent),
multi: true
}]
})
export class InputComponent extends FormField implements ControlValueAccessor {
@Input() type = 'text';
@Input() placeholder: string;
@Input() autocomplete: ChoiceSource;

autocompleteChoices: ChoiceList;

@Input() set value(value: string) {
this.innerValue = value == null ? '' : String(value);
}
get value() {
return this.innerValue;
}

@Input() set disabled(value: any) {
this.setDisabledState(getFlagAttribute(value));
}
get disabled() {
return this.isDisabled;
}

private changeCallback: Function;
private touchedCallback: Function;

isDisabled = false;
innerValue = '';

displayText(value: ChoiceModel): string {
return value.text;
}

writeValue(value: any) {
if (!this.autocomplete) {
this.value = value;
}
}
registerOnChange(fn: Function) {
this.changeCallback = fn;
}
registerOnTouched(fn: Function) {
this.touchedCallback = fn;
}
setDisabledState(isDisabled: boolean) {
this.isDisabled = isDisabled;
}

inputHandler(event: Event) {
this.value = (<HTMLInputElement>event.target).value;
if (this.changeCallback) {
this.changeCallback(this.value);
}
}

autocompleteHandler(event: Event) {
const text = (<HTMLInputElement>event.target).value;
if (this.autocomplete) {
if (text) {
this.autocompleteChoices = this.autocomplete(text);
} else if (this.changeCallback) {
this.innerValue = '';
this.changeCallback(null);
}
}
}

autocompleteBlur(event: Event) {
(<HTMLInputElement>event.target).value = this.innerValue;
this.setTouched();
}

updateOption(event: MatAutocompleteSelectedEvent) {
if (this.changeCallback) {
const { value, text } = event.option.value;
this.value = text;
this.changeCallback(value);
}
}

setTouched() {
if (this.touchedCallback) {
this.touchedCallback();
}
}
}

现在我将举一个使用它们的例子:

简单的输入大小写

<my-input type="text" name="myInputName" [(ngModel)]="myNgModel" placeholder="---" required pattern="[a-zA-Zàèìòù\'\s0-9\.]+">
</my-input>

自动完成输入案例

export myClass implements OnInit, AfterViewInit, ControlValueAccessor, AfterViewChecked {

@ViewChild('BirthTown') BirthTown: InputComponent; //from import

public autocompleteSourceBirthTown: Function;

this.autocompleteSourceBirthTown = (async function(input: string) {
if (input.trim().length > 2) {
const towns = await this.generalService.getListBirthTowns(input.trim());
return towns;
}
return [];
}).bind(this);

// only for text of town
ngAfterViewChecked() {
if (this.BirthTown && this.BirthTownNgModel) {
const textTown = this.stateService.getDataBirthTown(this.BirthTownNgModel);
if (textTown) {
this.textBirthTown = textTown;
}
}
<seg-input #BirthTown [(ngModel)]="BirthTownNgModel" placeholder="BirthTown"  [autocomplete]="autocompleteSourceBirthTown" [value]="textBirthTown" required>
</seg-input>

希望能帮到你

关于angular - 如何编写 Angular Material 表单控件组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48217958/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com