【问题标题】:angular - custom validator with http callangular - 带有 http 调用的自定义验证器
【发布时间】: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


【解决方案1】:

您对未指向正确范围的“this”有疑问。

“简单”的解决方法是在您的服务提供者中使用胖箭头功能,以确保“this”指向服务提供者:

代替:

public count(control: FormControl) {

做:

public count = (control: FormControl) => {

现在您的代码仍然需要解决其他问题(例如响应对象的解析无效)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-01
    • 2016-08-13
    • 2019-11-09
    • 2018-01-19
    • 2019-01-07
    • 2018-01-18
    • 2019-10-10
    • 2016-05-13
    相关资源
    最近更新 更多