以编程方式更新Angular 2字段

VSO*_*VSO 7 javascript angular

我有以下表单字段,工作正常.通过这种方式,我的意思是当我在字段中键入,粘贴等时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>
Run Code Online (Sandbox Code Playgroud)

但是,我someDate在这个领域有这个指令.该指令拦截粘贴事件.它取消了粘贴事件,对输入进行了一些奇特的格式化,然后执行此操作:

setTimeout(() => {
  this.target.value = 'lol fancy date';
}, 3000);
Run Code Online (Sandbox Code Playgroud)

target.value是我的someDate领域.值在输入框内得到了很好的更新(我看到它在输入内的屏幕上发生了变化).但是,fooObj.someDate未更新并且不会进行验证.例如,在超时中设置目标值不会触发与键入/粘贴/任何其他javascript事件相同的验证/对象更新.

Angular docs对此没什么用处:

只有当应用程序响应异步事件(例如击键)时,Angular才会更新绑定(以及屏幕).此示例代码将keyup事件绑定到数字0,可能是最短的模板语句.虽然该语句没有任何用处,但它满足Angular的要求,因此Angular将更新屏幕.

那么,如何从该字段的指令触发字段更新?

编辑:我尝试使用我元素中的代码触发注释中建议的元素上的事件:如何手动触发onchange事件?

运行正常,但不强制该字段更新:

  if ("createEvent" in document) {
    var evt = document.createEvent("HTMLEvents");
    evt.initEvent("change", false, true);
    this.target.dispatchEvent(evt);
  }
  else
    this.target.fireEvent("onchange");
Run Code Online (Sandbox Code Playgroud)

此外,这里是我得到合成事件的想法,不会触发"正常"的行为作为一个keyDown或任何会(我真的希望我误读或他们错误的这个用例,但它不适用于尝试重新发布粘贴事件):https://www.w3.org/TR/clipboard-apis/#clipboard-event-interfaces

注意:合成事件没有默认操作.换句话说,虽然上面的脚本将触发粘贴事件,但数据实际上不会粘贴到文档中.

sil*_*sod 3

我不知道你指令的细节,但我可以猜测你的意图。首先,我们将订阅valueChanges控件的可观察对象,并避免直接在控件上绑定两种方式,以避免过多的写入和检查:

表单.html

<input tabindex="2"
             type="tel"
             class="form-control"
             maxlength="7"
             placeholder="MM/YY"
             formControlName="someDate"
             name="someDate"
             someDate />
Run Code Online (Sandbox Code Playgroud)

表单.ts

这是我们订阅的地方(它可以移出构造函数,取决于您何时制作表单)。

constructor() {
    this.myForm = new FormGroup({
        someDate: new FormControl(''),
    });

    this.myForm.controls['someDate'].valueChanges.subscribe(
      value => this.fooObj.someDate = value;
      );
  }
Run Code Online (Sandbox Code Playgroud)

某个日期.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);
  }
}
Run Code Online (Sandbox Code Playgroud)

更改paste为而不是input仅捕获onpaste事件。这有点奇怪,preventDefault()因为输入实际上消失了一段时间。

这是一个笨蛋:http://plnkr.co/edit/hsisILvtKErBBOXECt8t ?p=preview

  • @VSO 很高兴我能帮忙。 (2认同)