How to call a service's method on ngOnInit with multiple components/routes

Kunepro picture Kunepro · Nov 2, 2016 · Viewed 9.3k times · Source

I have several routes that are nothing more than a static page.
On each of these routes (over 50) I have to call a couple of methods (and more) on two different services when the route is initiated.
A simple working solution is that on each page I call the ngOnInit method and call the aforementioned methods.
The issue is that this means copying and pasting the same code over 50 different files. Copying and pasting is bad, it is not maintainable.

To make an example:

I have the page "FAQ" (manually assigned id: 52) and the page "Find Us" (manually assigned id: 13). These are 2 different routes.
I have the service "Editor", that is used to edit those page from an Admin panel and it needs to keep track of what page I'm seeing.
I have the service "Cache", that checks if the page was already queried to the backend before or if it needs to be pulled from the server.
Both these service want to know the ID that I manually assigned to that route.
The ID in this specific case is used to query the database/API, however this detail is not question-centric and shouldn't invalidate the answer for other people with similar issues.

// Page FAQ
id: number
constructor() {
  this.id = 52; // 52 is the id that I assigned to the page FAQ
}
ngOnInit () {
  editorService.keepTrack(this.id);
  editorService.moreMethod().notMaintainable().whatIfIChangeSomething(this.id/0);
  cacheService.keepTrack(this.id);
}

// Page Find Us
id: number
constructor() {
  this.id = 13; // 13 is the id that I assigned to the page Find Us
} 
ngOnInit () {
  editorService.keepTrack(this.id);
  editorService.moreMethod().notMaintainable().whatIfIChangeSomething(this.id/0);
  cacheService.keepTrack(this.id);
}

Now, this is a simplified example as I don't see the need to overload the question with details that are not related to the issue at hand.

The only solution that I can think of, is to make a third service. This will call the methods on other two.
So in every page I only have to call this single service method on the ngOnInit and leave the implementation about how to call the other two to this third service.
This would minimize copying and pasting and would leave the implementation in a single manteinable file.

To make an example:

// Page FAQ v2
id: number
constructor() {
  this.id = 52;
}
ngOnInit() {
  inceptionService.doStuff(this.id);
}

// Page Find Us v2
id: number
constructor() {
  this.id = 13;
}
ngOnInit() {
  inceptionService.doStuff(this.id);
}

// InceptionService
export class InceptionService {
  doStuff(data) {
  editorService.keepTrack(data);
  editorService.moreMethod().notMaintainable().whatIfIChangeSomething(data/0);
  cacheService.keepTrack(data);
  }
}

The question is:
Is there a better way to do this? I have a feeling that I'm not doing it using the best approach.
It still feels like I'm abusing the services.

Answer

Michal Dymel picture Michal Dymel · Nov 2, 2016

You can create a base class for these routes and make your components inherit from this base class.

export class BaseComponent {
    ngOnInit() {
        //your service calls
    }
}

export class MyStaticComponent1 extends BaseComponent {
    ngOnInit() {
        super.ngOnInit();
        //component specific calls
    }
}