Angular2 RC4 debounceTime仍会在每次按键时调用

时间:2016-08-01 15:20:13

标签: angular angular2-forms

我有一个验证指令,用于检查客户端密钥是否唯一。在检查网络流量并看到它正在为每次按键调用时,一切似乎都按预期工作。

import { Directive, forwardRef, ReflectiveInjector } from '@angular/core';
import { AbstractControl } from '@angular/common';
import { FormControl, NG_VALIDATORS } from '@angular/forms';

import {Observable} from 'rxjs/Rx';

import {DomainService} from '../services/domain.service';

interface IRefIdValidator {
}

function validateRefIdFactory(domainService : DomainService) {
  return (control: AbstractControl): Observable<IRefIdValidator> => {

    // get the domain Id and Ref Id key 
    let domainId: number = +control.root.find('domainId').value;
    let clientId: number = +control.root.find('clientId').value;
    let key: string = control.value;

    // Return an observable with null if the
    // reference id check comes back successful
    return new Observable((obs: any) => {
      control
        .valueChanges
        .debounceTime(500)
        .distinctUntilChanged()
        .flatMap(value => domainService.checkDomainClientKey(domainId, clientId, key))
        .subscribe(
        data => {
          obs.next(null);
          obs.complete();
        },
        error => {
          obs.next({ refId: true });
          obs.complete();
        }
        );
    });
  };
}

@Directive({
  selector: '[validateRefId][formControlName],[validateRefId][ngModel],[validateRefId][formControl]',
  providers: [
    DomainService, 
    { provide: NG_VALIDATORS, useExisting: forwardRef(() => RefIdValidatorDirective), multi: true }
  ]
})
export class RefIdValidatorDirective {
  validator: Function;

  constructor(
    private domainService: DomainService
    ) {
      console.log('RefIdValidatorDirective created');
    this.validator = validateRefIdFactory(this.domainService);
  }

  validate(c: AbstractControl) {
    return this.validator(c);
  }
}

我在模型驱动的形式中使用此验证指令:

 this.domainForm = this.fb.group({
      clientKey: ['', Validators.required, new RefIdValidatorDirective(this.domainService).validator]
    });

正如您所看到的,这也是无效的,因为我将domainService从父组件传递给验证指令,但是,我一直无法弄清楚如何以任何其他方式将服务注入此指令

这是我的网络跟踪的样子,即使我正在快速打字:

24?key=Test
24?key=TestA
24?key=TestAB
24?key=TestABC

对此有任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:1)

您的代码存在问题:您没有返回Observable,而是返回Subscription,因为您正在订阅并返回。

要做到这一点,最好创建s Subject去抖动每次击键。这是一个很好的做法,你可以适应你的需求。每次击键都会调用onSearch方法:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';

@Component({...})
export class ExampleComponent implements OnInit, OnDestroy {
 private searchTermStream = new Subject<string>();
 private searchSubscription: Subscription;

  ngOnInit() {
    this.searchSubscription = this.createInputSubscriber();
  }

  ngOnDestroy() {
    this.searchTermStream.complete();
  }

  onSearch(query: string): void {
    this.searchTermStream.next(query);
  }

  private createInputSubscriber(): Subscription {
    return this.searchTermStream
      .distinctUntilChanged()
      .debounceTime(500)
      .subscribe((query: string) => console.log(query));
  }
}

这里我们还在组件被销毁时清除ngOnDestroy方法中的内存。