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.
答案 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