angular - 使用http调用的自定义验证器

时间:2018-05-29 11:28:07

标签: angular forms validation

我在这里重新创建了这个问题

https://stackblitz.com/edit/angular-custom-validator-issue

您可以分叉设置(右上角),然后根据需要进行编辑

基本上我试图在我的被动表单设置中创建一个自定义验证器,它接受表单输入的值,并向Datamuse API发送一个http请求,用于计算字符串中音节的数量。然后根据响应结果我返回错误或成功。我已经遵循了角度文档,但我的解决方案是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]],
      });
  }
}

音节count.service

    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;      
          }
      }
    }

1 个答案:

答案 0 :(得分:2)

你有'this'的问题没有指向正确的范围。

“简单”修复是在服务提供商中使用胖箭头功能,以确保'this'指向服务提供商:

代替:

public count(control: FormControl) {

<强>做的:

public count = (control: FormControl) => {

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

相关问题