Как составить Angular Компоненты управления формой материала
В приведенном ниже коде показан элемент формы автозаполнения, который позволяет выбирать состояние в США.
<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. Например. Нужно реализовать MatFormFieldControl. Руководство, представленное Angular Материалом, больше направлено на создание нового элемента управления формой с использованием примитивных элементов, а не на использование/обертку существующих элементов управления формой Angular.
Цель состоит в том, чтобы иметь возможность сделать что-то вроде этого в форме:
<mat-form-field>
<lookup-state placeholder="State of Residence" required="true" formControlName="resState">
</lookup-state>
</mat-form-field>
Ответы
Ответ 1
Я собираюсь вставить свой пример компонента, используя Angular Материал. Я создал пользовательский компонент ввода (два случая: простой ввод или автозаполнение):
это мой 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>
Ответ 2
У меня была такая же проблема, если вы хотите создать компонент-оболочку для автозаполнения. Ниже приведена моя реализация, которая работает в реактивных и управляемых шаблонами формах. Для этого вам необходимо реализовать ControlValueAccessor
. Если вы также имеете некоторую проверку, которую хотите переместить в компонент, вы также можете реализовать интерфейс Validator
.
У меня возникла проблема с тем, что mat-form-field
не был помечен как недопустимый, хотя элемент управления формами фактически недействителен. Это комментарий к проблеме "Стили не применяются, если FormField обернут настраиваемым компонентом" и этот связанный plunker помог мне исправить это.
autocomplete.component.html:
<mat-form-field>
<input #input matInput type="text" class="form-control" [matAutocomplete]="autocomplete" (input)="valueChanged($event)" [readonly]="readonly"
(focus)="$event.target.select()" (blur)="onTouched()">
<mat-autocomplete #autocomplete="matAutocomplete" [displayWith]="displayFunction" (optionSelected)="onOptionSelected($event)">
<mat-option *ngFor="let option of filteredOptions" [value]="option">
{{ displayFunction(option) }}
</mat-option>
</mat-autocomplete>
</mat-form-field>