<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 updates the bindings (and therefore the screen) only if the app does something in response to asynchronous events,such as keystrokes. This example code binds the keyup event to the number 0,the shortest template statement possible. While the statement does nothing useful,it satisfies Angular’s requirement so that Angular will update the screen.
那么,如何从该字段的指令触发字段更新?
编辑:我尝试使用我的元素上的代码: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");
此外,这里是我得到合成事件的想法,不会触发“正常”行为作为keyDown或任何会(我真的希望我误读或他们错误的这个用例,但它不适用于尝试重新发布粘贴事件):https://www.w3.org/TR/clipboard-apis/#clipboard-event-interfaces
NOTE:
Synthetic events do not have default actions. In other words,while the script above will fire a paste event,the data will not actually be pasted into the document.
解决方法
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); } }
更改为粘贴而不是输入以仅捕获onpaste事件.使用preventDefault()有点奇怪,因为输入有效地消失了一段时间.