Greg
Greg

Reputation: 1024

Inject service in a simple class constructor with Angular2

I created a Message class like this

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

import { ApiService } from '../api.service';

export class Message {
        timestamp: number;
        message: any;
        api: ApiService;

        constructor(message: any) {
                let injector = ReflectiveInjector.resolveAndCreate([ApiService]);
                this.api = injector.get(ApiService);
                this.timestamp = message.timestamp;
                this.message = message.message;
        }
}

I'm not injecting ApiService directly in the constructor parameters because I'm trying to avoid this: let nm = new Message(message, this.api)
I don't want the service to be in the parameters.

So I'm using the ReflectiveInjector but this code doesn't even work. I get this error : EXCEPTION: Error: Uncaught (in promise): No provider for Http! (ApiService -> Http) even if I include HTTP_PROVIDERS this way

import { bootstrap } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { HTTP_PROVIDERS } from '@angular/http';

import { AppComponent, environment } from './app/';
import { appRouterProviders } from './app/app.routes';

if (environment.production) {
  enableProdMode();
}

bootstrap(AppComponent, [
        appRouterProviders,
        HTTP_PROVIDERS,
])
.catch(err => console.log(err));

How can I use the constructor to instantiate my class and inject my services like this :
let nm = new Message(message);

Thanks

Upvotes: 6

Views: 5047

Answers (3)

Hesse
Hesse

Reputation: 41

For some reason my answer was deleted without explanation, so here's the answer again:

This is exactly what I have been wondering; What if you really need to call a constructor in your code & still need to inject some things in your class? For example Angular2 tutorial's Hero class is anemic and does not contain any real-world functionality. That's not the case in my application, I need to have a domain objects that contain (a lot of) logic.

Anyway, this is my approach:

@Injectable()
export class MessageFactory {
  constructor(private service: Service)

  build(data: any): Message {
    let message = new Message(data);
    message.service = this.service;
    return message;
  }
}

export class Message {
  service: Service;

  constructor(private data: any) {
    // Can't call service here but it's okay for me...
  }

  doSomethingWithService(): {
    this.service.doSomething(this.data);
  }
}

So somewhere you can inject MessageFactory and create new instances of Messages:

export class MessageExampleComponent {
  constructor(private messageFactory: MessageFactory) {}

  makeMessageDoSomethingWithService(): {
    let message = this.messageFactory.build({just: 'an', example: 'here'})
    message.doSomethingWithService();
  }
}

I'm not sure if calling it MessageFactory is even a correct term, but I would like to have a feedback on this approach before some moderator just deletes this post without comment.

Upvotes: 4

Jorawar Singh
Jorawar Singh

Reputation: 7621

I solved it by using @Inject

import { Inject } from "@angular/core;

and i think it should work like this

@Inject(ApiService) api: ApiService;

import { Injectable , Inject } from "@angular/core;
    @Injectable()
    export class apiService {
        public constructor(@Inject(Http)  private http: Http) {}

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

import { ApiService } from '../api.service';

@Component({
     providers: [ HomeService  ]
})

export class Message {
        timestamp: number;
        message: any;
        api: ApiService;

        constructor(message: any, @Inject(ApiService) api:ApiService) {                                      
                this.timestamp = message.timestamp;
                this.message = message.message;
        }
}

Upvotes: 2

rashfmnb
rashfmnb

Reputation: 10578

you can use it while doing bootstrap like this

let nm = new Message(message);

bootstrap(AppComponent, [ 
  APP_ROUTER_PROVIDERS,
  [provide(Message,{useValue:nm})],
]).catch(err => console.error(err));

and for this

EXCEPTION: Error: Uncaught (in promise): No provider for Http! (ApiService -> Http)

in service create constructor and import the HTTP like this

import { Http, Response } from '@angular/http';
export class LoginService {

  constructor(private http: Http) {

  }
}

for this purpose

Oh sorry, this is not how I want to use my class. For every message in the chat I'm making, I instantiate a Message. I don't want just one global Message class but several Message objects.

bootstrap(AppComponent, [ 
  APP_ROUTER_PROVIDERS,
  Message //you service here
]).catch(err => console.error(err));

Upvotes: 2

Related Questions