Angular2:当jquery插件附加到ng-form对象时如何触发ng-valid?

Posted

技术标签:

【中文标题】Angular2:当jquery插件附加到ng-form对象时如何触发ng-valid?【英文标题】:Angular2: How to trigger ng-valid when jquery plugin is attached to ng-form object? 【发布时间】:2017-07-28 12:11:42 【问题描述】:

我使用 Angular2 ng-form,我喜欢它如何自动判断表单上的所有控件是否有效,如果有效,则启用我的表单提交按钮。 但是,如果我在其中一个控件上使用了一个很酷的 jquery 插件,例如我的示例中的 datedropper,那么在底层输入控件有效之前,表单将保持无效。

这是我的表单 html

    <form name="submitForm" #submitForm="ngForm">
      <div class="group">
        <input class="spring-date spring-input" data-large-mode="true" data-large-default="true" required readonly type="text" name="docdate" [(ngModel)]="docdate" #inputdocdate="ngModel">
      </div>
      <div class="group">
        <input class="spring-input" required type="text" name="company" [(ngModel)]="company" #inputcompany="ngModel">
      </div>
      <div class="group">
        <button id="btnSave" type="submit" class="btn btn-default" [disabled]="!submitForm.form.valid">SAVE</button>
      </div>
    </form>

这是激活 datedropper 的 jquery(我在我的 TypeScript 组件中执行此操作):

ngOnInit() 
        // Initialize Datedropper jquery select box
        $('.spring-date').dateDropper();
    );

即使我在 datedropper jquery 更改事件中更新我的 TS 代码中的双重绑定 docdate 值,在我开始输入另一个文本框之前,表单也不会确定它是有效的控制。

$('.spring-date').on('change', (e: any) => 
            this.docdate = $(e.target).val();                
        );

如何使用 jquery 插件(如 datedropper 或 Select2)并在用户更改值后更新 jquery 中的底层输入控件并同时激活 Angular2 表单验证?

我唯一的其他选择是放弃内置的 Angular2 验证并编写代码来手动验证所有控件。我觉得我错过了一个简单的解决方法。

【问题讨论】:

【参考方案1】:

在您的情况下,在角度区域内调用 onChange 将对您有所帮助:

$('.spring-date').dateDropper().on('change', (e: any) => 
   // console.log(Zone.current.name); // prints <root>
   this.ngZone.run(() => 
     // console.log(Zone.current.name); // prints angular
     this.docdate = e.target.value;
   );
);

如何使用 jquery 插件(如 datedropper 或 Select2)及之后 用户更改值,更新底层输入控件 jquery 同时激活 Angular2 表单验证?

我会像这样实现ControlValueAccessor:

export const DATE_DROPPER_VALUE_ACCESSOR: any = 
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => DateDropperValueAccessor),
  multi: true
;

@Directive(
  selector: 'input.spring-date',
  providers: [DATE_DROPPER_VALUE_ACCESSOR]
)
export class DateDropperValueAccessor implements ControlValueAccessor 
  constructor(private _renderer: Renderer, private _elementRef: ElementRef, private ngZone: NgZone)  

  writeValue(value: any): void 
    this._renderer.setElementProperty(this._elementRef.nativeElement, 'value', value);
  

  ngOnInit() 
    $(this._elementRef.nativeElement).dateDropper().on('change', (e: any) => 
      this.ngZone.run(() => this.onChange(e.target.value));
    );
  

  onChange = (_: any) =>  ;
  onTouched = () =>  ;

  registerOnChange(fn: (_: any) => void): void  this.onChange = fn; 
  registerOnTouched(fn: () => void): void  this.onTouched = fn; 

Plunker Example

另见

AngularJS 2 input field does not update ngModel for Jquery Date Picker date change

【讨论】:

this.ngZone.run 修复效果非常棒!对于使用此修复程序的其他人,请不要忘记您需要添加: import NgZone from '@angular/core';和构造函数(私有ngzone:NgZone)到你的构造函数。谢谢。

以上是关于Angular2:当jquery插件附加到ng-form对象时如何触发ng-valid?的主要内容,如果未能解决你的问题,请参考以下文章

如何检索 jquery 插件附加到的目标元素?

angular2采用自定义指令(Directive)方式加载jquery插件

Angular2动态组件和TP jQuery库

如何在Angular2中使用jQuery及其插件的方法

在 Jquery 插件模板中绑定 Angular2 组件

Angular2 - 将 div 添加到 DOM