Same Code in Multiple Components Angular 6

Viewed 1918

I have a couple of components that are doing the same job. Everyone makes the same API call only with a different parameter:

this.http.get('url' + parameter).subscribe((data: Array<any>) => {
   //some state dispatches and other stuff
   return response;
});

I don´t want to write the same code in every component for reasons. In Java for example I use superclasses for this case. In Angular services are sufficient most of the time. But not in this case.

I tried to write a new class:

export class Content {
   constructor(private http: HttpClient) { }
   getContent() {
     this.http.get('url' + parameter).subscribe((data: Array<any>) => {
       //some state dispatches and other stuff
       return response;
     });      
   }
}

Now I can initialize this class in every component and it works:

export class MyComponent {
  constructor(private http: HttpClient) { }
  toggle() {
    new Content(http);
  }
}

The issue is that I have to use the constructor where I injected the HttpClient. I don´t want that because I have to pass additional dependencies(which are not relevant for the issue).

So is that the best practice and if yes how can I use HttpClient without passing it?

4 Answers
  • You should be using map in your service to perform common processing before the result is returned to the component.
  • The service should return an observable to the calling component. The component can then further process the result from that point.
  • This might just be for the example but do not use any if it can be helped, define an interface instead and use that to define the response and return types. This adds type safety to your code which is one of the primary reasons that typescript was created to begin with.
  • You should be injecting the service into the component. Really you should always use injection for any dependencies. If you have different actions you want to execute create different methods to handle them in your service or create methods that take parameters. In my experience there is no reason to manually create instances of HttpClient.

The following is a very common approach for what I think you are asking.

import { map } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class ContentService {
   constructor(private http: HttpClient) { }

   getContent() : Observable<Array<any>> {
     return this.http.get<Array<any>>('url' + parameter).pipe(map((data: Array<any>) => {
       // common processing here
       return data;
     }));
   }
}
@Component({})  
export class MyComponent {
  constructor(private contentService: ContentService) { }

  data: Array<any> = [];
  toggle() {
    this.contentService.getContent().subscribe(data => {
      // do something with returned data like...
      this.data = data;
    });
  }
}

Just put @Injectable before create the class of the service, and then you can inject the service inside the providers of app.module.ts

@Injectable()
export class Service {
  constructor(
      private http: HttpClient,
  ) {}

  getContent() {
     this.http.get('url' + parameter).subscribe((data: Array<any>) => {
       //some state dispatches and other stuff
     });      
   }
}

And then you can use it inside the constructor of your other component importing the service before :)

constructor(private service: Service) { }

Create a Service. Import the service in any component that you need, and inside the Service import the HttpClient.

Here are the docs.

Create a service with httpClient. use a function which returns a promise. inside this function use http request. In your component just get the instance of the service and execute whatever you want after promise returns a value

service.ts

 export class ContentService {
   constructor(private http: HttpClient) { }
   getContent(): Promise<any> {
     this.http.get('url' + parameter).subscribe((data: Array<any>) => {
       return new Promise(resolve => resolve('whatever'));
     });      
   }
}

component.ts

constrctor (private classService: ClassService) {
   classService.getContent()
   .then(data => 'do whatever you want with tha data');
}
Related