【发布时间】:2018-12-15 20:09:47
【问题描述】:
我在这里重新创建了问题
https://stackblitz.com/edit/angular-custom-validator-issue
您可以分叉设置(右上角),然后随意编辑
基本上,我试图在我的反应式表单设置中创建一个自定义验证器,该验证器获取表单输入的值并向 Datamuse API 发送一个 http 请求,该 API 计算字符串中的音节数。然后根据响应结果,我返回错误或成功。我遵循了角度文档,但我的解决方案是 http 调用有问题,我相信这与调用堆栈顺序有关。所以我需要关于如何实现这一点的帮助,我认为这将有助于我更好地理解 Angular。
app.component
import { Component, ElementRef } from '@angular/core';
import { FormControl, FormBuilder, FormGroup, Validators, AbstractControl } from '@angular/forms';
import { VERSION } from '@angular/material';
import { SyllableCountValidator } from './syllable-count.service';
@Component({
selector: 'material-app',
templateUrl: 'app.component.html'
})
export class AppComponent {
version = VERSION;
public poemForm: FormGroup;
constructor(private fb: FormBuilder, private scv: SyllableCountValidator) {
this.createForm();
}
//ERRORS APPEAR IN CONSOLE after INPUT into 'input text' in the dom
// 1. create form group with entry inputText. Initialise it with no value
// and set the validation to a custom validator called 'count' that is
// located in the 'private scv: SyllableCountValidator' service
// go to syllable-count.service file to see next steps
createForm() {
this.poemForm = this.fb.group({
inputText: ['', [this.scv.count]],
});
}
}
音节计数服务
import { ValidatorFn, AbstractControl, FormControl } from '@angular/forms';
import { forEach } from '@angular/router/src/utils/collection';
import { Injectable } from '@angular/core';
import { HttpClient, HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class SyllableCountValidator {
constructor(private http: HttpClient) {}
// 2. create http request to datamuse API that returns a syllable
// count repsonse for requested text
public requestCount(text): Observable<Object> {
return this.http.get(`https://api.datamuse.com/words?sp=${text}&md=s`) as Observable<Object>;
}
// 3. on any input into the formControl 'inputText' this will fire
public count(control: FormControl) {
// 4. split the string received from the fromControl
// 'textInput' into an array
const arrayOfStrings = control.value.split(' ');
// 5. define empty text variable
let text = '';
// 6. loop through step 3. arrayOfStrings and concatonate into
// correct format for http call and push to text variable in step 4.
const pushToText = Array.prototype.forEach.call(arrayOfStrings, function(word) {
text = `${text}+${word}`;
});
// 7. trim first character of text variable in step 4. to remove
// unessecary '+' character
const trimmedText = text.substr(1);
// 8. call requestCount() in step 2. and return validation result
if (trimmedText) {
const validateSyllables = this.requestCount(trimmedText).subscribe((response) => {
// 8.1.1 if syllable count is greater than 5 return error
// of number of syllables it is greater by
if ( response[0].numSyllables > 5 ) {
return {
error: 5 - response[0].numSyllables
}
// 8.1.2 if syllable count is less than 5 return error
// of number of syllables it is less by
} else if ( response[0].numSyllables > 5 ) {
return {
error: 5 - response[0].numSyllables
}
// 8.1.3 if syllable count equals 5 return validation
// success as required by angular of 'null'
} else if ( response[0].numSyllables == 5 ) {
return null;
}
});
// 9.2. return validation result
return validateSyllables;
}
}
}
【问题讨论】:
-
您对“this”有疑问,我会在几分钟内为您链接一个固定表单
-
现在只需确保正确解析对象...解决方法是通过 var 和粗箭头函数分配您的方法,以使服务提供商的 this 对函数透明
-
您在订阅回调中返回结果,这没有意义,请查看文档angular.io/guide/form-validation,基本上,您应该编写一个返回
AsyncValidatorFn的函数,而不是调用subscribe你应该使用map函数并返回 observable -
谢谢我是一名学生,所以这对结构方面的建议有很大帮助,我确实阅读了角度文档,但对我来说没有多大意义,我会给出你的建议
标签: angular forms validation