Reputation: 441
I am using ionic4 and Angular 7.2.2, and I created a base component class to be extended by other components and not have to repeat a lot of things that I always use. In order to avoid the constructor injection, and therefore be forced to pass again the params to the base construtor in th extended class, I am using Injector.get.
The problem that experience is that, when used it this way, a lot of Angular or Ionic injectors that work fine if injected in the child constructor, do not work or return empty values when used in the child, using the parent's reference.
I am sure there is something I am missing out, because upon inspection of the injector when using the one from my base class and the one from the child, they are different.
Uppon execution, and going to: http://localhost:8101/home/4
This is the relevant code:
app-routing.module.ts
const routes: Routes = [
{path: '', redirectTo: 'home/4', pathMatch: 'full'},
{path: 'home/:id', loadChildren: './home/home.module#HomePageModule'},
];
home.page.ts
import {Component} from '@angular/core';
import {BasePage} from '../../tests/base.comp.test';
import {ActivatedRoute} from '@angular/router';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage extends BasePage {
constructor(public ar: ActivatedRoute) {
super();
this.activatedRoute.params.subscribe(
(result) => {
console.log(`PARAMS FROM inherited activatedRoute-> `, result); // -> outputs {} WRONG!
}
);
ar.params.subscribe(
(result) => {
console.log(`Params from direct injection-> `, result); // -> outputs {id: "4"} Good!
}
);
}
}
home.module.ts
import {NgModule} from '@angular/core';
import {RouterModule} from '@angular/router';
import {HomePage} from './home.page';
import {BasePageModule} from '../../tests/base.test.module';
@NgModule({
imports: [
BasePageModule,
RouterModule.forChild([
{
path: '',
component: HomePage
}
])
],
declarations: [HomePage]
})
export class HomePageModule {
}
base.test.module.ts
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {IonicModule} from '@ionic/angular';
import {FormsModule} from '@angular/forms';
import {BasePage} from './base.comp.test';
@NgModule({
imports: [
CommonModule,
IonicModule,
FormsModule,
],
declarations: [BasePage],
providers: [],
exports: [
CommonModule,
IonicModule,
FormsModule
]
})
export class BasePageModule {
}
base.comp.test.ts
import {Component, Injector} from '@angular/core';
import {AppInjectorTest} from './app.injector.test';
import {ActivatedRoute, Router} from '@angular/router';
@Component({
selector: 'app-base',
template: '',
})
export class BasePage {
public injector: Injector;
public activatedRoute: ActivatedRoute;
constructor() {
const injector = AppInjectorTest.getInjector();
this.activatedRoute = injector.get(ActivatedRoute);
}
}
app.injector.test.ts
import {Injector} from '@angular/core';
export class AppInjectorTest {
private static injector: Injector;
static setInjector(injector: Injector) {
AppInjectorTest.injector = injector;
}
static getInjector(): Injector {
return AppInjectorTest.injector;
}
}
app.component.ts
import {Component, Injector} from '@angular/core';
import {Platform} from '@ionic/angular';
import {SplashScreen} from '@ionic-native/splash-screen/ngx';
import {StatusBar} from '@ionic-native/status-bar/ngx';
import {AppInjectorTest} from '../tests/app.injector.test';
@Component({
selector: 'app-root',
templateUrl: 'app.component.html'
})
export class AppComponent {
constructor(
private platform: Platform,
private splashScreen: SplashScreen,
private statusBar: StatusBar,
private injector: Injector
) {
this.initializeApp();
AppInjectorTest.setInjector(injector);
}
initializeApp() {
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.splashScreen.hide();
});
}
}
Upvotes: 1
Views: 979
Reputation: 441
For now it seems that the only workaround we want to do this is to re-inject the injector from the child into the parent. It is not as clean as keeping the constructor completely empty, but, at least, you can extend and reuse a lot of logic from a parent component in a neat way.
child.comp.ts (that extends from parent)
constructor(public injector: Injector) {
super(injector);
}
(...)
parent.comp.ts
(...)
constructor(public injector: Injector) {
this.activatedRoute = injector.get(ActivatedRoute);
}
(...)
Upvotes: 2
Reputation: 24424
there is nothing wrong with your static injector but it related how activatedRoute work , ActivatedRoute contains the information about a route associated with a component. loaded in an outlet doc , thay whay the injected activatedRoute (component) work instad of base injected activatedrouteservice
when using a parametrized route which targets a component, only this component can access those parameters.
check this question has similar problem 👉 How to retrieve a route param using Injector.get(ActivatedRoute)?
Upvotes: 1