【问题标题】:Angular2 RC6 HttpModule manual injectionAngular2 RC6 HttpModule 手动注入
【发布时间】:2017-01-17 07:56:06
【问题描述】:

我正在将一个项目从 angular2 RC4 迁移到 RC6,并且我有一个需要 Http 的自定义表单验证器。 在迁移之前,我使用了 ReflectiveInjectorHTTP_PROVIDERS,但是对于 RC6,这是不可能的,因为 HTTP_PROVIDERS 已被弃用,分别不再存在。 这是Validator中的静态方法:

    static checkVat(control: FormControl) {
    let checkVatUrl = "http://localhost:8080/checkvat";


    let injector = ReflectiveInjector.resolveAndCreate([HTTP_PROVIDERS]);
    let http = injector.get(Http);
    let authHttp = new AuthHttp(new AuthConfig(), http);

    if (control.value === "") {
        return new Observable((obs: any) => {
            obs.next(null);
            obs.complete();
        });
    } else {
        return authHttp.get(checkVatUrl + "/" + control.value)
            .map((data: Response) => {
                if (data.json().valid) {
                    return null;
                } else {
                    let reason = "isNotValidVat";
                    return {[reason]: true};
                }
            })
            .catch(function (e) {
                return new Observable((obs: any) => {
                    obs.complete();
                });
            });
    }
}

只是用HttpModule 替换HTTP_PROVIDERS 不起作用,我在stackoverflow (NG2 RC5: HTTP_PROVIDERS is deprecated) 上发现了一个关于测试的类似问题,但唯一的答案是特定于测试的。

我如何使用 RC6 手动“注入”HttpHttpModule,如果此自定义验证器有其他或更好的解决方案,我也愿意。

提前致谢。

更新: checkVat 方法是静态的,这就是为什么我必须使用 ReflectiveInjector 而不仅仅是通过构造函数注入它,就像其他地方一样。 自定义验证器的使用方式如下:

this.vatCtrl = new FormControl("", Validators.compose([Validators.pattern(this.vatService.vatPattern)]),VatValidator.checkVat);

更新2: 在 Günther Zöchbauer 的回答的帮助下,我将代码更改如下,使其在没有静态函数且无需手动注入的情况下工作:

验证者:

@Injectable()

导出类VatValidator {

constructor(private http: Http) {
}

checkVat(control: FormControl) {

    let checkVatUrl = "http://localhost:8080/checkvat";

    let authHttp = new AuthHttp(new AuthConfig(), this.http);

    if (control.value === "") {
        return new Observable((obs: any) => {
            obs.next(null);
            obs.complete();
        });
    } else {
        return authHttp.get(checkVatUrl + "/" + control.value)
            .map((data: Response) => {
                if (data.json().valid) {
                    return null;
                } else {
                    let reason = "isNotValidVat";
                    return {[reason]: true};
                }
            })
            .catch(function (e) {
                return new Observable((obs: any) => {
                    obs.complete();
                });
            });
    }

}

}

在具有 FormControl 的组件中:

    constructor(private vatValidator: VatValidator) {

    this.vatCtrl = new FormControl("", Validators.compose([Validators.pattern(vatPattern)]), this.vatValidator.checkVat.bind(this.vatValidator));

}

【问题讨论】:

  • 为什么需要let injector = ReflectiveInjector.resolveAndCreate([HTTP_PROVIDERS]); 而不仅仅是constructor(private http:Http){}
  • 因为checkVat 是静态的。我会将这种方法的使用添加到我的问题中。
  • 为什么需要是静态的?
  • 如果我将此函数设为非静态并创建VatValidator 的实例,则此方法的调用(显示在问题的更新中)对我不起作用。 checkVat 的参数是 Validator 应用到的 FormControl,如果我使用实例 (vatValidator) 并像这样调用方法:vatValidator.checkVat(this.vatCtrl) 由于参数,编译器不喜欢那样。这是一个 AsyncValidator。

标签: angular typescript angular2-forms angular2-injection


【解决方案1】:

在 RC5 之后,您可以做的是,

import { HttpModule} from '@angular/http';
@NgModule({
  imports:      [ BrowserModule,HttpModule ],  //<------HttpModule
  declarations: [ AppComponent],
  providers:    [service],

  bootstrap:    [ AppComponent ]
})

并且在服务或组件中,

import { Http, Response } from '@angular/http';
@Injectable()
export class service{
  constructor(private http:Http){}           //<----inject here

  // use http here
}

【讨论】:

  • 谢谢,这不起作用,因为我的方法是静态的,我更新了我的问题。
【解决方案2】:

如果你稍微改变你的验证器类,你就不需要静态方法

@Injectable()
class PatternValidator {
  constructor(private http:Http){}

  // this is a method that returns a validator function  
  // configured with a pattern
  pattern(pattern) {
    return (control:Control) => {
      this.http.get(...)

    ...
    }
  }
}

你可以像这样使用它:

  • 将其注入到您的组件中,以便 DI 将其依赖项传递到 (Http)
constructor(private pattern:PatternValidator) {}
  • 使用bind(pattern) 传递它,以便.this 继续在验证器函数中工作
this.vatCtrl = new FormControl("", 
    Validators.compose([
        this.pattern(this.vatService.vatPattern).bind(this.pattern)
    ]), VatValidator.checkVat);

另请参阅 Inject Http manually in angular 2

【讨论】:

  • 谢谢,我会试试这个,虽然我需要这个自定义 AsyncValidator VatValidator.checkVat 而不是模式验证器,它是 angular2 原生的,我还不确定如何使用它它在这段代码中:this.vatCtrl = new FormControl("", Validators.compose([ this.pattern(this.vatService.vatPattern).bind(pattern) ]), VatValidator.checkVat);
  • 抱歉混淆了这些。 checkVat 应该同样有效。 this.vatCtrl = new FormControl("", Validators.compose([ this.pattern(this.vatService.vatPattern)]), this.vatValidator.checkVat.bind(this.vatValidator))
  • 如果您发布更多代码(不在评论中 - 编辑问题),我可以提供更具体的反馈。
  • 太好了,很高兴听到 :)
【解决方案3】:
import { ReflectiveInjector } from '@angular/core';
import { Http, XHRBackend, ConnectionBackend, BrowserXhr, ResponseOptions, XSRFStrategy, BaseResponseOptions, CookieXSRFStrategy, RequestOptions, BaseRequestOptions } from '@angular/http';

class MyCookieXSRFStrategy extends CookieXSRFStrategy {}

...

let http =  ReflectiveInjector.resolveAndCreate([
        Http, BrowserXhr, 
        { provide: ConnectionBackend, useClass: XHRBackend },
        { provide: ResponseOptions, useClass: BaseResponseOptions },
        { provide: XSRFStrategy, useClass: MyCookieXSRFStrategy },
        { provide: RequestOptions, useClass: BaseRequestOptions }
      ]).get(Http);

当然,您仍然需要包含 HttpModule,享受吧!

【讨论】:

  • 这很好用但是很笨重。 @AlexV 您是否将此作为功能请求提交给 Anuglar 团队以改进此功能并使其更容易?
  • 感谢您的回答。我需要这个。同意@ScottN,希望有更好的方法来获取现有的 Http 服务。
  • 在 Angular 4.0.0-rc3 中出现错误:Cannot resolve all parameters for 'MyCookieXSRFStrategy'。在这里找到解决方案:stackoverflow.com/questions/39243525/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-17
  • 1970-01-01
  • 1970-01-01
  • 2020-01-02
  • 2017-01-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多