我有以下表单字段,工作正常。通过这种方式,我的意思是当我在字段中键入,粘贴等时,fooObj.expDate
实时更新得很好并且验证发生。我有预标签,这对我自己来说很明显。
<pre>{{fooObj.someDate | json}}</pre>
<div class="form-group inline-form__input">
<label for="someDate">Some Date</label>
<input tabindex="2"
type="tel"
class="form-control"
maxlength="7"
placeholder="MM/YY"
formControlName="someDate"
name="someDate"
[(ngModel)]="fooObj.someDate"
someDate>
</div>
但是,我在这个字段上有someDate
指令。该指令拦截粘贴事件。它取消了粘贴事件,对输入做了一些奇特的格式化,然后执行此操作:
setTimeout(() => {
this.target.value = 'lol fancy date';
}, 3000);
target.value
是我的someDate
字段。值在输入框内得到了很好的更新(我看到它在输入内的屏幕上发生了变化)。但是,fooObj.someDate
未更新,并且不会进行验证。例如。在超时中设置目标值不会触发与键入/粘贴/任何其他javascript事件相同的验证/对象更新。
Angular docs对此没有多大帮助:
Angular仅在应用程序执行某些操作以响应异步事件(例如击键)时更新绑定(以及屏幕)。此示例代码将keyup事件绑定到数字0,可能是最短的模板语句。虽然该语句没有任何用处,但它满足Angular的要求,因此Angular将更新屏幕。
那么,如何从该字段的指令触发字段更新?
编辑:我尝试使用我的元素上的代码在评论中推荐的元素上触发事件:How can I trigger an onchange event manually?
运行正常,但不强制更新字段:
if ("createEvent" in document) {
var evt = document.createEvent("HTMLEvents");
evt.initEvent("change", false, true);
this.target.dispatchEvent(evt);
}
else
this.target.fireEvent("onchange");
此外,我在这里得到的合成事件的概念没有触发&#34;正常&#34;作为keyDown或其他任何操作的行为(我真的希望我误读或者他们错误地使用这个用例,但它没有尝试重新发布粘贴事件):https://www.w3.org/TR/clipboard-apis/#clipboard-event-interfaces
注意: 合成事件没有默认操作。换句话说,虽然上面的脚本将触发粘贴事件,但数据实际上不会粘贴到文档中。
答案 0 :(得分:3)
我不知道您指令的详细信息,但我可以猜测您的意图。首先,我们将订阅我们控件的valueChanges
observable并直接避开控件上的双向绑定,以避免过多的写入和检查:
<强> form.html 强>
<input tabindex="2"
type="tel"
class="form-control"
maxlength="7"
placeholder="MM/YY"
formControlName="someDate"
name="someDate"
someDate />
<强> form.ts 强>
这是我们订阅的地方(它可以移出构造函数,取决于您何时制作表单)。
constructor() {
this.myForm = new FormGroup({
someDate: new FormControl(''),
});
this.myForm.controls['someDate'].valueChanges.subscribe(
value => this.fooObj.someDate = value;
);
}
<强>一些-date.directive.ts 强>
该指令会将值写入控件,然后valueChanges
的订阅将更新我们的模型。这适用于粘贴事件和其他所有事件(因此您可以限制目标事件,但我想至少确保粘贴有效)。
@Directive({
selector: '[someDate]'
})
export class SomeDateDirective{
constructor(private el: ElementRef, private control : NgControl) {
}
@HostListener('input',['$event']) onEvent($event){
$event.preventDefault();
let data = $event.clipboardData.getData('text');
setTimeout(() => {
this.control.control.setValue(data.toUpperCase());
}, 3000);
}
}
更改为paste
而不是input
,仅捕获onpaste
个事件。它与preventDefault()
有点奇怪,因为输入有效地消失了一段时间。
这里是一名掠夺者:http://plnkr.co/edit/hsisILvtKErBBOXECt8t?p=preview