如何解决如何为 Angular Material 构建自定义 formGroup 组件
我目前正在研究如何创建时间范围选择器。我的目的是开发一个类似于下面的 mat-date-range-input 组件的组件,用于没有 datepickerpicker-toggle 和 mat-date-range-picker 的时间范围(我只需要用户输入和用户条目的合并):>
<mat-form-field appearance="fill">
<mat-label>Dates</mat-label>
<mat-date-range-input [formGroup]="daterange" [rangePicker]="datePicker">
<input matStartDate placeholder="Start date" formControlName="dateStart" (dateInput)="onDateChange('dateStart',$event)" />
<input matEndDate placeholder="End date" formControlName="dateEnd" (dateInput)="onDateChange('dateEnd',$event)" />
</mat-date-range-input>
<mat-datepicker-toggle matSuffix [for]="datePicker"></mat-datepicker-toggle>
<mat-date-range-picker #datePicker></mat-date-range-picker>
</mat-form-field>
从现在开始我尝试了几件事,最简单的是使用 controlContainer 并在 ngContainer 中构建我的组表单,这导致了这个错误:
core.js:4196 ERROR 错误:mat-form-field 必须包含 MatFormFieldControl
所以接下来我尝试按照本教程创建自定义组件:tutorial angular material 这并不是我想要知道我正在寻找构建一组两个输入控件的内容。 我遇到了和 controlContainer one 一样的问题:
mat-form-field 必须包含一个 MatFormFieldControl。
我的实际组件模板如下:
<div
role="group"
class="time-picker-container">
<input type="time" formControlName="timeStart" min="1" max="24"/>
<span class="mat-date-range-input-separator">–</span>
<input type="time" formControlName="timeEnd" min="1" max="24"/>
</div>
我实现该组件的尝试如下:
export interface TimeRange {
timeStart: string;
timeEnd: string;
}
@Component({
selector: 'time-range-picker',templateUrl: './time-range-picker.component.html',styleUrls: ['./time-range-picker.component.scss'],providers: [{provide: [MatFormFieldControl,NG_VALUE_ACCESSOR],useExisting:
TimeRangePickerComponent}]
})
export class TimeRangePickerComponent implements MatFormFieldControl<TimeRange>,ControlValueAccessor
{
@input()
formGroup: FormGroup;
@input()
get value() : TimeRange | null {
let fg = this.formGroup.value;
if (fg.timeStart !== null && fg.timeEnd !== null){
return { timeStart: fg.timeStart,timeEnd: fg.timeEnd};
}
return null;
}
set value(value: TimeRange | null) {
value = value || { timeStart: '',timeEnd: ''};
this.formGroup.setValue({ hourStart: value.timeStart,timeStart: value.timeStart});
this.stateChanges.next();
}
stateChanges: Subject<void>;
static nextId = 0;
@HostBinding() id = `time-range-picker-${TimeRangePickerComponent.nextId++}`;
private _placeholder: string;
@input()
get placeholder() {
return this._placeholder;
}
set placeholder(value) {
this._placeholder = value;
this.stateChanges.next();
}
focused: boolean = false;
get empty() : boolean {
let p = this.formGroup.value;
return !p.hourStart && !p.hourEnd && !p.minutesstart && !p.minutesEnd;
}
@HostBinding('class.floating')
get shouldLabelFloat() {
return this.focused || !this.empty;
}
private _required : boolean = false;
@input()
get required() : boolean {
return this._required;
}
set required(req) {
this._required = coerceBooleanProperty(req);
this.stateChanges.next();
}
private _disabled: boolean = false;
@input()
get disabled(): boolean { return this._disabled; }
set disabled(value: boolean) {
this._disabled = coerceBooleanProperty(value);
this._disabled ? this.formGroup.disable() : this.formGroup.enable();
this.stateChanges.next();
}
errorState: boolean = false;
controlType?: string = 'time-range-picker';
autofilled?: boolean;
@Input('aria-describedby') userAriaDescribedBy: string;
setDescribedByIds(ids: string[]): void {
const controlElement = this.elRef.nativeElement
.querySelector('.time-range-picker-container')!;
controlElement.setAttribute('aria-describedby',ids.join(' '));
}
onContainerClick(event: MouseEvent): void {
if ((event.target as Element).tagName.toLowerCase() != 'input') {
this.elRef.nativeElement.querySelector('input').focus();
}
}
constructor(fb: FormBuilder,private fm: FocusMonitor,private elRef: ElementRef<HTMLElement>,@Optional() public parentFormField: MatFormField,@Optional() @Self() public ngControl: NgControl)
{
fm.monitor(elRef,true).subscribe(origin => {
this.focused = !!origin;
this.stateChanges.next();
});
}
writeValue(obj: any): void {
if (obj != undefined) this.formGroup.setValue(obj);
}
registerOnChange(fn: any): void {
this.formGroup.valueChanges.subscribe(fn);
}
registerOnTouched(fn: any): void {
throw new Error('Method not implemented.');
}
setdisabledState?(isdisabled: boolean): void {
throw new Error('Method not implemented.');
}
ngOnDestroy(): void {
this.stateChanges.complete();
this.fm.stopMonitoring(this.elRef);
}
}
这个问题是我在父组件中有两个不同的formControls,它们以这样的形式(反应形式)链接它们:
this.timeRange = new FormGroup({
timeStart: new FormControl(this.filtersInput.timeRange.timeStart),timeEnd: new FormControl(this.filtersInput.timeRange.timeEnd),});
this.form = this.formBuilder.group({
timeRange: this.timeRange
});
如果您对如何实现该功能有任何想法或建议。
提前感谢您阅读和分享您的知识!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。