derpawe derpawe - 3 months ago 145
TypeScript Question

Angular2 RC6 HttpModule manual injection

I'm migrating a project from angular2 RC4 to RC6 and I have a custom Form Validator which needs

Http
.
Before the migration I used the
ReflectiveInjector
with the
HTTP_PROVIDERS
, but with RC6 this is not possible anymore as
HTTP_PROVIDERS
is deprecated, respectively not present anymore.
This is the static method in the 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();
});
});
}
}


Just replacing
HTTP_PROVIDERS
with
HttpModule
didn't work, I found a similar problem here on stackoverflow (NG2 RC5: HTTP_PROVIDERS is deprecated) regarding testing, but the only answer is specific for testing.

How do I manually "inject"
Http
or
HttpModule
with RC6, if there is another or better solution for this custom Validator I'm open to that too.

Thanks in advance.

UPDATE:
The
checkVat
method is static, that is why I had to use the ReflectiveInjector and not just inject it via the constructor, like everywhere else.
The custom Validator gets used like this:

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


UPDATE2:
With the help of Günther Zöchbauer's answer I changed the Code as follows to get it working without a static function and no need for manual injection:

The Validator:

@Injectable()


export class 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();
});
});
}

}


}

In the component which has the FormControl:

constructor(private vatValidator: VatValidator) {

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

}

Answer

If you change your validator class a bit, you don't need a static method

@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(...)

    ...
    }
  }
}

You can use it like:

  • inject it to your component so DI passes it's dependencies in (Http)
constructor(private pattern:PatternValidator) {}
  • pass it with bind(pattern) so .this keeps working inside the validator function
this.vatCtrl = new FormControl("", 
    Validators.compose([
        this.pattern(this.vatService.vatPattern).bind(this.pattern)
    ]), VatValidator.checkVat);