FormControls(模板驱动和响应式)通过实现ControlValueAccessor 的指令订阅值和写入值。看看相关的方法selectValueAccessor,它在所有必要的指令中都有使用。普通输入控件(例如<input type="text">)或文本区域由DefaultValueAccessor 处理。另一个例子是CheckboxValueAccessor,它应用于复选框输入控件。
这项工作一点也不复杂。我们只需要为日期输入控件实现一个新的值访问器。
DateValueAccessor 是个好名字:
// date-value-accessor.ts
import { Directive, ElementRef, HostListener, Renderer, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
export const DATE_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DateValueAccessor),
multi: true
};
/**
* The accessor for writing a value and listening to changes on a date input element
*
* ### Example
* `<input type="date" name="myBirthday" ngModel useValueAsDate>`
*/
@Directive({
selector: '[useValueAsDate]',
providers: [DATE_VALUE_ACCESSOR]
})
export class DateValueAccessor implements ControlValueAccessor {
@HostListener('input', ['$event.target.valueAsDate']) onChange = (_: any) => { };
@HostListener('blur', []) onTouched = () => { };
constructor(private _renderer: Renderer, private _elementRef: ElementRef) { }
writeValue(value: Date): void {
this._renderer.setElementProperty(this._elementRef.nativeElement, 'valueAsDate', value);
}
registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
registerOnTouched(fn: () => void): void { this.onTouched = fn; }
setDisabledState(isDisabled: boolean): void {
this._renderer.setElementProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
}
}
我们将DateValueAccessor附加到多提供者DATE_VALUE_ACCESSOR,以便selectValueAccessor可以找到它。
唯一的问题是,应该使用哪个选择器。我决定选择加入解决方案。
这里 DateValueAccessor 选择属性“useValueAsDate”。
<input type="date" name="myBirthday" ngModel useValueAsDate>
OR
<input type="date" name="myBirthday" [(ngModel)]="myBirthday" useValueAsDate>
OR
<input type="date" formControlName="myBirthday" useValueAsDate>
也可以修复默认实现。
以下选择器将神奇地激活该功能。
// this selector changes the previous behavior silently and might break existing code
selector: 'input[type=date][formControlName],input[type=date][formControl],input[type=date][ngModel]'
但请注意,这可能会破坏依赖旧行为的现有实现。所以我会选择选择加入版本!
这一切都在 NPM 和 Github 上
为了您的方便,我在 Github 上创建了项目 angular-data-value-accessor。
还有一个 NPM 包可用:
npm install --save angular-date-value-accessor
然后通过 NgModule 导入模块:
// app.module.ts
import { DateValueAccessorModule } from 'angular-date-value-accessor';
@NgModule({
imports: [
DateValueAccessorModule
]
})
export class AppModule { }
现在您可以将“useValueAsDate”应用于您的日期输入控件。
演示
当然,这里有一个演示:
http://johanneshoppe.github.io/angular-date-value-accessor/