gpt4 book ai didi

javascript - Angular 2 ngModel 变异指令

转载 作者:太空宇宙 更新时间:2023-11-04 16:02:45 25 4
gpt4 key购买 nike

我想构建一个指令,可以改变传入和传出输入的值,并与 ngModel 绑定(bind)。

假设我想做一个日期突变,每次模型更改时,突变器首先将值更改为正确的格式(例如“2017-05-03 00:00:00”显示为“2017/05/03"),在 ngModel 更新 View 之前。当 View 更改时,变元会在 ngModel 更新模型之前更改值(例如输入“2017/08/03”将模型设置为“2017-08-03 00:00:00”[时间戳])。

该指令的使用方式如下:

<input [(ngModel)]="someModel" mutate="date:YYYY/MM/DD" />

我的第一 react 是获取对 Host 组件上的 ControlValueAccessor 和 NgModel 的引用。

import { Directive, ElementRef, Input, 
Host, OnChanges, Optional, Self, Inject } from '@angular/core';
import { NgModel, ControlValueAccessor,
NG_VALUE_ACCESSOR } from '@angular/forms';


@Directive({
selector: '[mutate]',
})
export class MutateDirective {

constructor(
@Host() private _ngModel: NgModel,
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR)
private _controlValueAccessor: ControlValueAccessor[]
){
console.log('mutute construct', _controlValueAccessor);
}


}

然后我意识到 Angular 2 Forms 类很复杂,我不知道我在做什么。有什么想法吗?

更新

根据下面的答案,我想出了解决方案:see gist

用法(需要 Moment JS):

<input  mutate="YYYY/MM/DD" inputFormat="YYYY-MM-DD HH:mm:ss" [(ngModel)]="someDate">

最佳答案

简短的回答:您需要在某个类中实现 ControlValueAccessor 并将其作为具有某些指令的 ngModel 的 NG_VALUE_ACCESSOR 提供。这个ControlValueAccessor和指令实际上可以是同一个类。

TL;DR这不是很明显,但也不是很复杂。下面是我的一个日期控件的骨架。这个东西充当 Angular 1 ng-model 的解析器/格式化器对。

这一切都始于 ngModel 将所有 NG_VALUE_ACCESSOR 注入(inject)自身。还有很多默认提供程序,它们都被注入(inject)到 ngModel 构造函数中,但是 ngModel 可以区分默认值访问器和用户提供的访问器。所以它会选择一个来合作。大致看起来像这样:如果存在用户的值访问器,那么它将被选择,否则它会回退到从默认值访问器中进行选择。初始设置完成后。

控制值访问器应该订阅输入元素上的“输入”或其他类似事件,以处理来自它的输入事件。

当值从外部更改时,ngModel 会在初始化期间选取的值访问器上调用 writeValue() 方法。此方法负责呈现显示值,该值将作为向用户显示的字符串进入输入。

在某些时候(通常是在模糊事件上)控件可以被标记为触摸。这也显示出来。

请注意:下面的代码不是真正的生产代码,尚未经过测试,它可能包含一些差异或不准确之处,但总的来说它显示了这种方法的整体思想。

import {
Directive,
Input,
Output,
SimpleChanges,
ElementRef,
Renderer,
EventEmitter,
OnInit,
OnDestroy,
OnChanges,
forwardRef
} from '@angular/core';
import {Subscription, Observable} from 'rxjs';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';

const DATE_INPUT_VALUE_ACCESSOR_PROVIDER = [
{provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DateInputDirective), multi: true}
];

@Directive({
// [date-input] is just to distinguish where exactly to place this control value accessor
selector: 'input[date-input]',
providers: [DATE_INPUT_VALUE_ACCESSOR_PROVIDER],
host: { 'blur': 'onBlur()', 'input': 'onChange($event)' }
})
export class DateInputDirective implements ControlValueAccessor, OnChanges {

@Input('date-input')
format: string;

model: TimeSpan;

private _onChange: (value: Date) => void = () => {
};

private _onTouched: () => void = () => {
};

constructor(private _renderer: Renderer,
private _elementRef: ElementRef,
// something that knows how to parse value
private _parser: DateParseTranslator,
// something that knows how to format it back into string
private _formatter: DateFormatPipe) {
}

ngOnInit() {

}

ngOnChanges(changes: SimpleChanges) {
if (changes['format']) {
this.updateText(this.model, true);
}
}

onBlur = () => {
this.updateText(this.model, false);
this.onTouched();
};

onChange = ($event: KeyboardEvent) => {
// the value of an input - don't remember exactly where it is in the event
// so this part may be incorrect, please check
let value = $event.target.value;
let date = this._parser.translate(value);
this._onChange(date);
};

onTouched = () => {
this._onTouched();
};

registerOnChange = (fn: (value: Date) => void): void => {
this._onChange = fn;
};

registerOnTouched = (fn: () => void): void => {
this._onTouched = fn;
};

writeValue = (value: Date): void => {
this.model = value;
this.updateText(value, true);
};

updateText = (date: Date, forceUpdate = false) => {
let textValue = date ? this._formatter.transform(date, this.format) : '';
if ((!date || !textValue) && !forceUpdate) {
return;
}
this._renderer.setElementProperty(this._elementRef.nativeElement, 'value', textValue);
}

}

然后在html模板中:

<input date-input="DD/MM/YYYY" [(ngModel)]="myModel"/>

关于javascript - Angular 2 ngModel 变异指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42140023/

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