6

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);

0

3 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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;
        }
}

9 Comments

Perfect. Thank you !
My bad. It worked until I use this.api which is undefined. I'm not sure how to use the @Inject() decorator. At the end, should I pass ApiService in the constructor like this: new Message(message, this.api) or ApiService will be injected without passing it in the constructor parameters ?
yes it should be in thhe constructor so when ever you use apiservice you can get http
My constructor looks like this constructor(message: any, @Inject(ApiService) api) { this.api = api; this.timestamp = message.timestamp; this.message = message.message; } I'm not really sure how to use @Inject() :/
if this is your message class then do this constructor(message: any, @Inject(ApiService) api:ApiService) { this.api = api; this.timestamp = message.timestamp; this.message = message.message; }
|
2

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));

1 Comment

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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.