我有角度可重用选择组件,它接受
formControlName
作为 @Input
。并渲染选择组件,选项作为子组件传递并在内部渲染<ng-content>
。
select.component.ts
import {Component, forwardRef, Input, OnInit} from '@angular/core';
import {FormControl, NG_VALUE_ACCESSOR} from '@angular/forms';
import {faChevronDown} from '@fortawesome/pro-solid-svg-icons';
@Component({
selector: 'component-select',
templateUrl: './select.component.html',
styleUrls: ['./select.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => SelectComponent),
}
]
})
export class SelectComponent implements OnInit {
@Input() formControlName: string;
public formControl: FormControl = new FormControl();
public onChange: (_: any) => void = () => {};
public onTouched: () => void = () => {}
constructor() {
}
ngOnInit(): void {
}
writeValue(obj: any): void {
this.formControl.setValue(obj);
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState?(disabled: boolean): void {
disabled ? this.formControl.disable() : this.formControl.enable();
}
protected readonly faChevronDown = faChevronDown;
}
select.component.html
<component-label><ng-content select="[slot=label]"></ng-content></component-label>
<div class="input-container">
<div class="left-icon"> <ng-content select="[slot=left-icon]"></ng-content></div>
<select class="form-input highlight-on-error" [formControl]="formControl" (change)="onChange(formControl.value)" >
<ng-content></ng-content>
</select>
<div class="right-icon"><fa-icon [icon]="faChevronDown"></fa-icon></div>
</div>
<component-error-message [controlName]="formControlName"></component-error-message>
该组件的使用很简单,它会从 FormGroup 接收表单控件作为 formControlName,在某些情况下表单控件会设置默认值。在这种情况下,
writeValue
将接收 obj 作为参数,并且它被正确传递,但 setValue
不会被调用,并且 select 具有空值。
用法
this.formBuilder.group({
nationality: [this.entry?.nationality === '' ? null : this.entry?.nationality]
});
<component-select formControlName="nationality">
<ng-container slot="label">{{ 'NATIONALITY_LABEL' | translate }}</ng-container>
<option [ngValue]="null"></option>
<option [ngValue]="option.code" *ngFor="let option of countries$ | async">{{ option.name }}</option>
</component-select>
问题是如果条目有国籍,那么它应该设置该值。目前尚未设置。如果在组件初始化之前加载值,我应该更改选择组件逻辑的哪一部分来设置值?
使用自定义表单组件时,无需读取表单控件名称和其他操作,一切都是自动的,我们所需要做的就是以正确的格式配置组件!
import {Component, forwardRef, Input, OnInit} from '@angular/core';
import {FormControl, NG_VALUE_ACCESSOR} from '@angular/forms';
import {faChevronDown} from '@fortawesome/pro-solid-svg-icons';
@Component({
selector: 'component-select',
template: `
<component-label><ng-content select="[slot=label]"></ng-content></component-label>
<div class="input-container">
<div class="left-icon"> <ng-content select="[slot=left-icon]"></ng-content></div>
<select class="form-input highlight-on-error" [value]="value"
[disabled]="disabled"
(focus)="markAsTouched()"
(change)="onChange(formControl.value)" >
<ng-content></ng-content>
</select>
<div class="right-icon"><fa-icon [icon]="faChevronDown"></fa-icon></div>
</div>
<component-error-message [controlName]="formControlName"></component-error-message>
`,
styleUrls: ['./select.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => SelectComponent),
}
]
})
export class SelectComponent implements OnInit {
value: any;
onChange = (quantity) => {};
onTouched = () => {};
touched = false;
disabled = false;
writeValue(value: any) {
this.value = value;
}
registerOnChange(onChange: any) {
this.onChange = onChange;
}
registerOnTouched(onTouched: any) {
this.onTouched = onTouched;
}
markAsTouched() {
if (!this.touched) {
this.onTouched();
this.touched = true;
}
}
setDisabledState(disabled: boolean) {
this.disabled = disabled;
}
protected readonly faChevronDown = faChevronDown;
}
即使上面的代码片段不起作用,请阅读这些文章以了解有关此方法的更多信息