【问题标题】:Angular2 - access the AbstractControl instance in validation directiveAngular2 - 在验证指令中访问 AbstractControl 实例
【发布时间】:2017-01-26 18:16:13
【问题描述】:

我必须从验证器指令内部触发验证。

这是我的指令。它按预期工作。但是我希望它在验证器函数更改时触发验证过程。 IE。当其输入变量maxDate 发生变化时。

我该怎么做?

如果我可以在构造函数中访问 AbstractControl 实例,我可以轻松做到这一点。但是,我想不出办法。

import { AbstractControl, FormGroup, ValidatorFn, Validator, NG_VALIDATORS, Validators } from '@angular/forms';
import { Directive, Input, OnChanges, SimpleChanges, EventEmitter } from '@angular/core';


function parseDate(date: string):any {  
  var pattern = /(\d{2})-(\d{2})-(\d{4})/;
  if (date) {
    var replaced = date.search(pattern) >= 0;    
    return replaced ? new Date(date.replace(pattern,'$3-$1-$2')) : null;
  }

  return date;
}


export function maxDateValidator(maxDateObj): ValidatorFn {
  return (control:AbstractControl): {[key: string]: any} => {    
    const val = control.value;

    let date = parseDate(val);
    let maxDate = parseDate(maxDateObj.max);    

    if (date && maxDate && date > maxDate) {
      return {
        maxDateExceeded: true
      };
    }
    return null;
  };
}

...

@Directive({
  selector: '[maxDate]',  
  providers: [{provide: NG_VALIDATORS, useExisting: maxDateDirective, multi: true}]  
})
export class maxDateDirective implements Validator, OnChanges {
  @Input() maxDate: string;

  private valFn = Validators.nullValidator;

  constructor() { }

  ngOnChanges(changes: SimpleChanges): void {
    const change = changes['maxDate'];
    if (change) {
      const val: string  = change.currentValue;      
      this.valFn = maxDateValidator(val);
    }
    else {
      this.valFn = Validators.nullValidator;
    }
    //This is where I want to trigger the validation again.
  }

  validate(control): {[key: string]: any} {
    return this.valFn(control);
  }
}

用法:

  <input type="text" [(ngModel)]="deathDateVal">

  <input class="form-control"          
          type="text"
          tabindex="1"
          [maxDate]="deathDateVal"
          name="will_date"
          [textMask]="{pipe: datePipe, mask: dateMask,  keepCharPositions: true}"
          ngModel
          #willDate="ngModel">

【问题讨论】:

  • 你的代码好像没问题,有什么问题?
  • 我想在验证参数更改时重新触发验证。即maxDate
  • 对不起,我不明白。每当任何输入更改时都会调用ngOnChanges,因此每当maxDate 更改时。您的代码应该可以正常工作。
  • 是的,确实如此。但是,验证过程不会被它触发。 willDate.errors 保持不变。
  • 只看代码,我不明白为什么。此外,您的代码几乎是 angular.io/docs/ts/latest/cookbook/… 的逐字代码,所以它应该可以工作......

标签: forms validation angular typescript angular2-directives


【解决方案1】:

这是我刚刚想出的:

@Directive({
  selector: '[maxDate]',  
  providers: [{provide: NG_VALIDATORS, useExisting: maxDateDirective, multi: true}]  
})
export class maxDateDirective implements Validator, OnChanges {
  @Input() maxDate: string;

  private valFn = Validators.nullValidator;
  private control:AbstractControl;

  constructor() { }

  ngOnChanges(changes: SimpleChanges): void {
    const change = changes['maxDate'];
    if (change) {
      const val: string  = change.currentValue;      
      this.valFn = maxDateValidator(val);
    }
    else {
      this.valFn = Validators.nullValidator;
    }

    if (this.control) {
      this.control.updateValueAndValidity(this.control);
    }
  }

  validate(_control:AbstractControl): {[key: string]: any} {
    this.control = _control;
    return this.valFn(_control);
  }
}

它有效。 Validate 在初始化时被调用,所以我只存储它的参数。 这他妈的丑陋,但它有效。

【讨论】:

  • 我正在寻找一种方法来获取指令中的控件以用于不同的目的。我从高处到低处搜索,并尝试了多种方法。这应该对我有用,虽然不理想。如果您对此有更多了解,请告诉我。
【解决方案2】:

要获得输入的 abstractControl,您可以执行以下操作:

@Directive({
  // tslint:disable-next-line:directive-selector
  selector: 'input[type=date][maxDate]'
})
export class InputFullWithDirective implements Validator, OnChanges {
  constructor(@Self() private control: NgControl) {}
  /** the rest is mostly unchanged from the question */
}

【讨论】:

    猜你喜欢
    • 2017-08-22
    • 2016-12-26
    • 2020-05-29
    • 1970-01-01
    • 2015-07-16
    • 1970-01-01
    • 2017-03-10
    • 2020-05-24
    • 2019-05-15
    相关资源
    最近更新 更多