kerosene
kerosene

Reputation: 873

Imported service is undefined on abstract class

I have abstracted class Collection, which utilizes a service Database to initialize collections on a database. I have several subclass instances of Collection, that all need to do the same database initialization. So Collection is some kind of base class.

Suprisingly, the imported service Database is undefined on the constructor of the subclass FooCollection. The constructor of the Database service is definitely called before the Foobar constructor.

Why is the imported service undefined on FooCollection?

Is this a reason of misconception or related to the loading order of classes?

Collection.ts:

import { Database } from '../providers/database';
import {Injectable} from "@angular/core";

@Injectable()
export abstract class Collection {

  public name : string;

  constructor(public db : Database) {
     // db is undefined here -> crash
     db.doSomething();
  }
}

Database.ts:

import {Injectable} from '@angular/core';
import 'rxjs/add/operator/map';

@Injectable()
export class Database {

  private _db: any = null;

  constructor() {
    console.log('Hello Database Provider');
  }

  public doSomething(): void {
      console.log("doSomething");
  }
}

FooCollection.ts:

import { Injectable } from '@angular/core';
import 'rxjs/add/operator/map';
import { Collection} from '../classes/collection';


@Injectable()
export class FooCollection extends Collection{
}

app.module.ts:

import { NgModule, ErrorHandler } from '@angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { Start } from '../pages/page/start';
import { Database } from '../providers/database';
import { FooCollection } from "../providers/foocollection";

@NgModule({
  declarations: [
    MyApp,
    Start
  ],
  imports: [
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    Start
  ],
  providers: [
    {provide: ErrorHandler, useClass: IonicErrorHandler},
    Database,
    FooCollection
   ]
})
export class AppModule {}

Start.ts:

import { Component } from '@angular/core';

import { NavController } from 'ionic-angular';

import { FooCollection } from '../../providers/foocollection';

@Component({
  selector: 'page-start',
  templateUrl: 'start.html'
})
export class Start{
  constructor(public navCtrl: NavController, public f: FooCollection ) {
  }
}

EDIT:

I noticed that explicitly importing Database again on FooCollection works fine:

import { Injectable } from '@angular/core';
import { Database } from './database';
import 'rxjs/add/operator/map';
import { Store } from '../classes/store';

@Injectable()
export class Calls extends Store {
  constructor(public db : Database) {
    super(db);
  }
}

This raises the question how imports are handled on subclasses of abstract classes.

Upvotes: 3

Views: 1913

Answers (2)

May
May

Reputation: 250

i cannot comment, so i write it here. i've just upgraded my app from 2.4.5 to 4.0.0 , and now i face the same issue ! i've got an abstract service (a) that injects a cache service (as protected) in extend that service (b) to add functionality.

and the extended service (b) is used in a resolver.

the resolver tries to call a method in service B, that uses one of the injected services in A. but those injected services are undefined. i've checked again , running in 2.4.5 - works like a charm

Upvotes: 0

Roman C
Roman C

Reputation: 1

You should provide db in the module where it's used. Foo collection should be also provided because see the plunk.

@NgModule({
  providers: [Database, FooCollection]

Upvotes: 2

Related Questions