6
votes

Given I have simple app component:

import {Component} from 'angular2/core';
import {bootstrap}    from 'angular2/platform/browser';
import {AppComponent}    from 'ng2-easy-table/app/app.component';
import {ConfigService} from "./config-service";

@Component({
  selector: 'app',
  directives: [AppComponent],
  providers: [ConfigService],
  template: `
    <ng2-table [configuration]="configuration"></ng2-table>
  `
})
export class App {
  constructor(private configuration:ConfigService) {}

}
bootstrap(App, []);

and ng2-table, which is being installed via npm install, and is placed in node_modules directory.

import {Component, OnInit, Input} from 'angular2/core';

@Component({
  selector: 'ng2-table',
})

export class AppComponent implements OnInit{
  @Input configuration;
  constructor() {
    console.log("configuration: ", this.configuration); // <-- null
  }

  ngOnInit() {
    console.log("configuration: ", this.configuration); // <-- null
  }
}

and this config service:

import {Injectable} from "angular2/core";
@Injectable()
export class ConfigService {
    public searchEnabled = true;
    public orderEnabled = true;
    public globalSearchEnabled = true;
    public footerEnabled = false;
    public paginationEnabled = false;
    public exportEnabled = true;
    public resourceUrl = "http://beta.json-generator.com/api/json/get/E164yBM0l";
}

In the app component I put ng2-table component. ng2-table and app are root components, so I am not allowed to use @Input() (this is the reason why [configuration]="configuration" does not work (following this answer https://stackoverflow.com/a/33155688/1168786).
The question is - how do I inject some service from app component into ng2-table component, but not using @Input().

How do I pass some config to my ng2-table, or even easier, how can I initialise component from node_modules which expects some config in constructor?

This is component link: https://github.com/ssuperczynski/ng2-easy-table/tree/master/app

5
I am having trouble figuring out how the service instance from the parent is shared with the child component in this example: angular.io/guide/…user5047085
Ah I think @James Salas answer answers my questionuser5047085

5 Answers

7
votes

Angular's dependency injection will provide the same instance of ConfigService to the child component as the parent component as long as it's not explicitly specified in the child component's providers property. This is due to Angular's hierarchal DI model, you can find more information in their docs. Based on the code samples, it looks like ConfigService might not using DI so you might want to look at turning it into an Injectable as well: DI info

5
votes

@Input in @Input configuration; is missing () it should be

@Input() configuration;

I copied your code to the Plunker and adding () fixed it.

Plunker example

1
votes

This line doesn't seem to be correct since I guess that you want to evaluate the configuration expression:

<ng2-table [configuration]="'configuration'"></ng2-table>

I would use the following instead

<ng2-table [configuration]="configuration"></ng2-table>

Moreover I would inject your service (if it's actually a service) this way:

(...)
import {ConfigService} from "./config-service";

export class App {
  constructor(private configuration: ConfigService) {
  }
}
0
votes

Why don't you simply inject by constructor the service that you are providing in the parent component?

You don't need to define extra inputs to pass the configuration. That's not a good practice.

@Component({
  selector: 'app',
  directives: [AppComponent],
  providers: [ConfigService],
  template: `
    <ng2-table></ng2-table>
  `
})
export class App {
  constructor(private configuration:ConfigService) {}

}

Then you can just inject the parent provider:

  @Component({
  selector: 'ng2-table',
})

export class AppComponent implements OnInit{
  
  constructor(private configuration:ConfigService) {
    console.log("configuration: ", this.configuration); // <-- null
  }

  ngOnInit() {
    console.log("configuration: ", this.configuration); // <-- null
  }
}
0
votes
export const LOCATION_SERVICE_PROVIDER: FactoryProvider = {
  provide: LocationService,
  deps: [
    [new Optional(), new SkipSelf(), LocationService],
  ],
  useFactory: function (
    parent: LocationService
  ) {
    return parent || new LocationService();
  }
};