Angular Parameterised Dependancy Injection

时间:2017-07-12 07:59:35

标签: angular

I am trying to figure out how to make a re-usable component in Angular. I am stuck in one particular aspect though. The component depends on a service (which has been made injectable). The service retrieves a list of items from a server. The URL to retrieve the items from however depends on the context of instantiation of the re-usable component using the service.

I have cobbled together an absolute minimal plunkr demonstrating this.

https://plnkr.co/edit/HcnGjEOFiDAq2HsNOYPY

The re-usable component here is in yygggg-list.component.*

The injectable service is in yygggg.service.ts. I have commented out the HTTP retrieve for the sake of the plunker and replaced with returning a fixed array but the URL in the HTTP retrieve is the aspect needing variability. More specifically this.realm:

return this.http.get("http://localhost/" + this.realm + ".php")
    .toPromise()
    .then(response => response.json() as string[])
    .catch(this.handleError);

There are now two contexts (I call them realms in the app) within which I wish to use the yygggg-list component: from METAR and SYNOP components. Barring the names, they are duplicates from one-another in the plunkr for simplicity (not in the real-life though). Here the SYNOPs (plural) component depends on the re-usable yygggg-list and a SYNOP (singular) component. The idea is to select an entry from the drop-down yygggg-list which washes through to selecting a specific SYNOP. Currently I pass the realm as a parameter to yygggg-list in the SYNOPs HTML.

<yygggg-list realm="synop" [(yygggg)]="selyygggg"></yygggg-list><br/>
<synop-capture [yygggg]="selyygggg"></synop-capture>

My current hack is to then pass this realm onto the service in the re-usable component's ngOnInit:

ngOnInit() : void
{
    this.yyggggsvc.realm = this.realm;
    ...
}

For this to work though the service's default value for realm needs to coincide with the default selected realm of the app on startup which is why i call it a hack as in yygggg.service.ts:

public realm: string = "synop";

I was hoping there is someone here understanding Angular well enough to assist me in getting rid of the hack and making this clean. The abstraction of a yygggg-list is really shareable between them, its just the URL that needs to vary so I can retrieve the list from the correct database table.

1 个答案:

答案 0 :(得分:1)

In the component where you provide the service you can also provide a configuration

@Component({
  ...,
  providers: [{provide: 'url', useValue: 'http:/...'}],
  template: '<yy-gggg-list></yy-gggg-list>',
)
export class ParentComponent {}

the service can then inject the config

constructor(private http: Http, @Inject('url') private url:String) {}    

Instead of just a string token you can also use an InjectionToken