在 Angular 7 中从现有函数创建用于验证的自定义指令?

Creating Custom Directives for Validation in Angular 7 from an existing function?

我在理解如何需要在 Angular 中创建自定义指令时遇到了一些困难。我有一个输入字段,用户需要输入一串字符,但它需要检查该字符串是否不包含某些子字符串。到目前为止,我已经完成了这个功能:

checkInvalidStrings(value, invalidValues) {
    let isKbWalk;
    let amount = [];
    invalidValues.forEach(string => {
        if (value.indexOf(string) > -1) {
            amount.push(string);
        } 
    })
    if (amount.length < 4) {
        isKeyboardWalk = false;
    } else {
        isKbWalk = true;
    }
    return isKbWalk;
}

我可以 运行 在组件文件中更改 ngModel 中的这个并且它完美地工作,我遇到的问题是我想 link 它与表单验证,所以如果它returns false,我希望它有效,如果它 returns true,我希望它无效。我相信我需要为此创建一个自定义验证器指令,但我遇到了一些麻烦。我想我要问的是如何使用上面的函数,以便我可以将它实现为一个指令来确定它是否有效?我正在使用模板驱动的表单,因为这是构建应用程序的方式,在这一点上保持一致比更改为响应式表单更简单。

通常我希望能够像这样对输入做一些事情,其中​​ kbWalk 是检查输入字段是否存在无效字符串的指令:

<input [(ngModel)]="data.newValue" name="newValue" #newValue="ngModel" required kbWalk>

到目前为止,我已将所有内容导入 app.module 文件,但验证工作不正常,这是我的指令设置:

import { Directive, forwardRef, Attribute } from '@angular/core';
import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms';
import { Invalid } from './invalidStrings';

@Directive({
    selector: '[kbWalk][ngModel]',
    providers: [
        { provide: NG_VALIDATORS, useExisting: KeyboardWalkValidator, multi: true }
    ]
})
export class KeyboardWalkValidator implements Validator {
    invalidStrings = Invalid.strings;

    constructor() { }

    validate(c: AbstractControl): { [key: string]: any } {
        return null;
    }
}

感谢您的帮助!

已解决:

import { Directive, forwardRef, Attribute, Input } from '@angular/core';
import { Validator, FormControl, NG_VALIDATORS } from '@angular/forms';
import { Invalid } from '../components/common/Invalid';

@Directive({
    selector: '[isKeyboardWalk][formControlName],[isKeyboardWalk][formControl],[isKeyboardWalk][ngModel]',
    providers: [ { provide: NG_VALIDATORS, useExisting: KeyboardWalkValidator, multi: true }
    ]
})
export class KeyboardWalkValidator implements Validator {
    invalid = Invalid.array;

    validate(c: FormControl): { [key: string]: any } {
        const val = c.value;
        return this.checkInvalidStrings(val) ? {'isKeyboardWalk': true} : null;
    } 

    checkInvalidStrings(value) { 
    // code for checking invalid value
    }
}

然后在视图中我只使用 isKeyboardWalk 指令:

<input type="text" isKeyboardWalk/>

我的问题是理解传递给验证函数的值实际上是来自表单的值,所以我可以在我的 checkInvalidStrings() 函数中将该值用于 运行 并且它工作正常.如果你们有选择,我会建议使用 Reactive Forms 并在下面的评论中实施解决方案,这也非常简单,帮助我了解更多。

我们可以使用自定义验证器来实现上述目的(我认为我们不需要为上述创建自定义指令)。以下对我有用。

customValidatorTest.ts 文件

import { AbstractControl } from '@angular/forms';

export function ValidateUrl(control: AbstractControl) {
  if ( !control.value.includes('.io')) {
    return { validUrl: true };
  }
  return null;
}

component.ts 文件

import { FormGroup, FormArray, FormBuilder,FormControl, Validators } from '@angular/forms';
import { ValidateUrl } from '../../customValidatorTest';
@Component({
  selector: 'app-educational-details',
  templateUrl: './educational-details.component.html',
  styleUrls: ['./educational-details.component.css']
})

export class EducationalDetailsComponent implements OnInit {
    educationalForm: FormGroup;

    constructor(private formBuilder: FormBuilder){}

    ngOnInit() {
         this.educationalForm= this.formBuilder.group({

            branch:['',[Validators.required,ValidateUrl]]
         })



    }

}

component.html 文件

 // adding only required functionality you directly write formGrop also 
 <tbody formArrayName="educationalDetails">
        <tr  *ngFor="let educationalDetail of educationalForm.controls.educationalDetails.controls; let $i=index" [formGroupName]="$i">

 <td><input  type="text" class="form-control my-1" formControlName="branch" ></td> //if branch input text box doesnt contain ".io" then it is invalid otherwise valid

关注 link 可能会有帮助

custom validatorar in reactive forms