I'm kinda new with Angular and I'm trying to build my app around it, but I'm having some troubles when injecting services in my Components.
I've added a 3rd party module with a service provider for translations in multiple languages on the fly, as it is kinda "hard" to do it manually, and a cookie service provider. The main problem is that the translation is made during template compilation, so to achieve that for my component I have to use a code like this:
<!-- language: typescript -->
import { Component, OnInit } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { CookieService } from 'ngx-cookie-service';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
language: string;
constructor(
private translateService: TranslateService,
private cookieService: CookieService) { }
ngOnInit() {
this.language = this.cookieService.get('lang') || 'en';
this.translator.use(this.language);
}
}
The main problem is that I have to pass those service providers everytime in the constructor function in every component, which is very repetitive. To prevent that, I've tried to create an abstract class
then extend it in my components as a base component. Something like this:
<!-- language: typescript -->
import { Injectable, OnInit } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { CookieService } from 'ngx-cookie-service';
@Injectable()
export abstract class DefaultComponent implements OnInit {
language: string;
constructor(private translator: TranslateService, private cookieService: CookieService) {
this.language = this.cookieService.get('lang') || 'es';
this.translator.use(this.language);
}
ngOnInit() {
//
}
}
<!-- language: typescript -->
import { Component } from '@angular/core';
import { DefaultComponent } from '../default.component';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent extends DefaultComponent {
ngOnInit() {
// Everything here replaces the ngOnInit from parent
}
}
This solution works for many of my components, but I have one component called PostsComponent
that uses a specific service provider to handle Posts
. This is the code:
<!-- language: typescript -->
import { Component } from '@angular/core';
import { DefaultComponent } from '../default.component';
import { Post } from '../../models/post';
import { PostService } from '../../services/post/post.service';
@Component({
selector: 'app-posts',
templateUrl: './posts.component.html',
styleUrls: ['./posts.component.css'],
providers: [ PostService ]
})
export class PostsComponent extends DefaultComponent {
posts: Post[];
constructor(private postService: PostService) { }
ngOnInit() {
this.getPosts();
}
getPosts(): void {
this.postService.getPosts().subscribe(posts => this.posts = posts);
}
}
If I use the constructor function for that component to use service provider, the parent constructor is overriden. To prevent that, I should call to super()
function in the constructor function, but I will have to send the TranslateService
and CookieService
to that function in order to make it work everything. As I said in the beginning, this is repetitive and I do not like that so much.
How can I achieve to load those common services for every component and still allowing to use specific services for specific components? I don't think setting up those common services as global variables is a good practice. Correct me if I'm wrong.
Thanks for your time.