Implementing manual injection of the HttpModule in Angular 2 RC6

During the migration of my project from angular2 RC4 to RC6, I encountered an issue with a custom Form Validator that requires the use of Http. Previously, I utilized ReflectiveInjector along with HTTP_PROVIDERS, but in RC6, this approach is not feasible anymore as HTTP_PROVIDERS has been deprecated and no longer available. The following 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();
                });
            });
    }
}

Replacing HTTP_PROVIDERS with HttpModule did not resolve the issue. I came across a similar problem on stackoverflow (NG2 RC5: HTTP_PROVIDERS is deprecated) related to testing, but the solution provided was specific to testing.

If there is a better or alternative solution for this custom Validator in RC6, I am open to suggestions.

Thank you in advance.

UPDATE: The checkVat method is static, which is why I had to use ReflectiveInjector instead of injecting it via the constructor like in other cases. The custom Validator is used as follows:

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

UPDATE2: Following Günther Zöchbauer's answer, I made the following changes to make it work without a static function and eliminate the 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 containing the FormControl:

    constructor(private vatValidator: VatValidator) {

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

}

Answer №1

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

Yes, including HttpModule is necessary in this scenario to ensure proper functionality. Enjoy using the code!

Answer №2

Modifying your validator class can eliminate the need for a static method

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

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

    ...
    }
  }
}

You can implement it in the following way:

  • Inject it into your component to allow Dependency Injection to pass its dependencies, such as Http, automatically.
constructor(private pattern:PatternValidator) {}
  • Bind it using bind(pattern) to ensure that .this continues working inside the validator function.
this.vatCtrl = new FormControl("", 
    Validators.compose([
        this.pattern(this.vatService.vatPattern).bind(this.pattern)
    ]), VatValidator.checkVat);

For more information, refer to Inject Http manually in angular 2

Answer №3

Once you have incorporated RC5, the possibilities are endless.

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

  bootstrap:    [ AppComponent ]
})

Whether it's in a service or component,

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

  // unleash the power of http here
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The NativeScript animation only triggers once

I have a NativeScript project with a ListView that triggers an event called "onItemTap." In this function I have written the following code snippet: onItemTap(args){ let clicked = args.view.bindingContext; let fav = this.page.getViewById("s ...

Angular2 - leveraging root-relative imports

Having trouble with imports in angular2/typescript? Want to use paths relative to the project root like 'app/components/calendar', but currently stuck using something like this: //app/views/order/order-view.ts import {Calendar} from '../../ ...

Tips for resolving the error message "Cannot use type 'string' to index type"

Currently, I am in the process of migrating a website from React to Next.js, and I am facing challenges when it comes to implementing i18n for SSR pages. I am following a tutorial provided at this link: I have already set up a lang folder and placed some ...

Transferring data between a ComponentPortal within an Angular CDK

After attempting to implement the method described in a Stack Overflow thread on Angular CDK: How to set Inputs in a ComponentPortal, I've encountered issues with the deprecated PortalInjector without clear guidance on what to use instead. The depreca ...

Issue with bootstrap modal new line character not functioning properly

Is there a correct way to insert a new line for content in a modal? I have this simple string: 'Please check the Apple and/or \nOrange Folder checkbox to start program.' I placed the '\n' newline character before "Orange," e ...

Switch up text colors on the fly in Angular as you type!

I've been developing a Note Taking application where users can type in red text. Additionally, they should also have the ability to change the color of the remaining text to black while typing. ...

Tips on adding an item to an array with React hooks and TypeScript

I'm a beginner with a simple question, so please bear with me. I'm trying to understand how to add an Object to the state array when a form is submitted. Thank you for your help! interface newList { name: string; } const ListAdder = () => { ...

What role does the @Input statement in the HeroDetailComponent class serve in the Angular 2 Quickstart tutorial?

Looking at the multiple components part of the Angular 2 Quickstart tutorial, we see how a component is separated from the AppComponent to enhance reusability and testing convenience. You can try out the example live demo here. In this scenario, users ar ...

Ensuring the visibility of a child entity post soft deleting its parent entity in TypeORM

Here are the entities I am working with: class Parent extends BaseEntity{ @Column() name:string @OneToMany( ()=>Child, (Child)=>Child.Parent ) Child:Child[] @DeleteDateColumn() ...

Here is a method to display a specific string in the mat-datepicker input, while only sending the date in the backend

enter image description hereIn this code snippet, there is a date input field along with a Permanent button. The scenario is that when the Permanent button is clicked, it should display "Permanent" in the input UI (nativeElements value), but the value bein ...

What is the reason behind permitting void functions in the left part of an assignment in Typescript?

Take a look at this Typescript snippet: let action = function (): void { //perform actions }; let result = action(); What makes it suitable for the TypeScript compiler? ...

How can I properly include DefinitelyTyped TypeScript definition files in a .NET Core project?

Previously, under asp.net for .net framework, I utilized NuGet to incorporate TypeScript type definitions from third-party libraries (*.d.ts files) provided by DefinitelyTyped. However, with the shift to .NET Core, it seems that NuGet is no longer recommen ...

Guide to vertically aligning text in an overlay using CSS within Angular 2

I currently have an overlay on my page that displays a spinner (an Angular material component) and accompanying text. This overlay covers the entire page and prevents clicking on elements below it. The spinner is positioned in the center of the page, and ...

When clicking the button, the service function is not properly updating the view

Upon calling this.getLeaderboard(); in the ngOnInit() function within leaderboard.component.ts, the leaderboard is only displayed on page load or refresh, which is expected. However, I also want to retrieve and display the leaderboard upon clicking a butto ...

Tips for updating the styles within a class for Angular 6 dynamically

Currently, I am able to update the button design using ng-container. Here is a snippet of the code: <ng-container *ngIf="isDisabled;"> <button class="bot-btn-disabled" (click)="confirm()" [disabled]=this. ...

Exploring the integration of external javascript AMD Modules within Angular2 CLI

During my experience with Angular2 pre-releases, I found myself using systemjs to incorporate external JavaScript libraries like the ESRI ArcGIS JavaScript API, which operates on AMD modules (although typings are available). Now that I am looking to trans ...

Strategies for Safely Assigning Firestore Data to an Object Without Losing Null Values

I am dealing with a class setup as follows: export class Car{ color=''; topSpeed=0; wheels = 4; } Within my Firestore database, there exists a document titled "car" with values: color:red topSpeed:230 (note that the 'wheels&a ...

Passing asynchronous data from method1 to method2 without impacting the functionality of the script responsible for fetching the asynchronous data in method1

When working with TypeScript, I encountered an issue while trying to invoke an external script called SPCalendarPro within a private method that asynchronously fetches data. The script is invoked in the following manner: private _getSPCalendarPro() { con ...

Exploring the use of two different array types in the useState hook with TypeScript

Working on a movie gallery project, I am utilizing an API to download movies and TV series. They are then displayed in a Row component where users can click on thumbnails to open them. The challenge arises with TypeScript, as the useState array can receiv ...

Installing failed due to an error in the postinstall script of @angular/core version 9

I'm at the beginning of my coding journey and I am looking to set up a source code on my computer. node -v v12.16.1 npm -v 6.13.4 Could you assist me in resolving this issue that arises when I try to run the npm install command (on Windows 7 ...