以编程方式更新Angular 2字段

时间:2016-11-29 14:30:52

标签: 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>

但是,我在这个字段上有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

  

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

1 个答案:

答案 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