将数组传递给自定义验证器Angular

时间:2017-08-04 09:32:04

标签: angular validation

我的模板:

          <input mdInput
                 [mdAutocomplete]="auto"
                 [(ngModel)]="formData.areaName"
                 (keyup)="updateFilteredAreas(formData.areaName)"
                 class="form-control {{areaName.errors && (areaName.dirty || areaName.touched) ? 'failed-validation' : ''}}"
                 name="areaName"
                 #areaName="ngModel"
                 arrayIncludes="one,two,three"
                 required>

          <div *ngIf="areaName.errors && (areaName.dirty || areaName.touched)"
               [hidden]="!areaName.errors.arrayIncludes"
               class="validation-error">
            Please enter a value from the array
          </div>

我的自定义验证器:

export class CustomValidators {

  public static arrayIncludes(arrayIncludes: string): ValidatorFn {
    return (control: AbstractControl): { [key: string]: any } => {
      if (isPresent(Validators.required(control))) {
        return null;
      }

      let arrayFromString = arrayIncludes.split(",");

      let value: string = control.value;

      return arrayFromString.includes(value) ?
        null :
        { arrayIncludes: { valid: false } };
    };
  }
}

辅助功能:

function isPresent(obj) {
    return obj !== undefined && obj !== null;
}

验证指令:

const ARRAY_INCLUDES_VALIDATOR = {
    provide: NG_VALIDATORS,
    useExisting: forwardRef(() => ArrayIncludesValidator),
    multi: true
};

@Directive({
  selector: '[arrayIncludes][ngControl],[arrayIncludes][ngFormControl],[arrayIncludes][ngModel]',
  providers: [ARRAY_INCLUDES_VALIDATOR]
})
export class ArrayIncludesValidator implements Validator {
  private _validator: any;

  constructor(@Attribute('arrayIncludes') arrayIncludes: string) {
    this._validator = CustomValidators.arrayIncludes(arrayIncludes);
  }

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

到目前为止,我可以将一个字符串作为值放入模板中的指令:

arrayIncludes="one,two,three"

然后将字符串转换为数组,结果只有&#34;一个&#34;,&#34;两个&#34;,&#34;三个&#34;值是允许的。我需要的是将一个对象从控制器传递给指令,该指令是一个对象数组。这些对象有&#34; area.name&#34;,以及每个&#34; area.name&#34;是一个有效的输入。当我使用语法时:

[arrayIncludes]="filteredAreas"

with&#34; filteredAreas&#34;作为我的对象,我得到的错误是

Error: Template parse errors:
Can't bind to 'arrayIncludes' since it isn't a known property of 'input'. ("
                 name="areaName"
                 #areaName="ngModel"
                 [ERROR ->][arrayIncludes]="filteredAreas"
                 required>

"): ng:///RegistrationModule/ConsumerFormComponent.html@42:21

如何重构我的自定义验证器以通过模板接受对象。它必须与&#34; @输入&#34;装饰。我的问题与此thread非常相似,但似乎缺少我需要的信息。

1 个答案:

答案 0 :(得分:4)

如果您想传递对象,则应使用@Input代替@Attribute

@Directive({...})
export class ArrayIncludesValidator implements Validator {
  private _validator: any;

  @Input() arrayIncludes: any;

  ngOnInit() {
    this._validator = CustomValidators.arrayIncludes(this.arrayIncludes);
  }

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