Reputation: 1861
I have a situation where I find myself replicating logic in parent components to fetch data from a server to populate a dropdown (this also includes handling pagination and search). I would therefore like to move this logic to the dropdown component where I can define it once.
However, this requires me defining which service the dropdown component should be using to fetch it's data. I would like to define this when I define the dropdown component in the parent.
For Example
<dropdown [service]="myService"></dropdown>
I could then call this function on the dropdown component passing parameters such as pagination and search parameters.
this.service(x,y,z).subscribe()
Is this possible?
I am also open to any other suggestions especially if I am looking at this the wrong way?
Upvotes: 3
Views: 5931
Reputation: 14958
Yes, it is possible. You could do something like this (StackBlitz):
1- Define an @Input()
property in the DropDownComponent
receiving the service (I created an interface in this case for better design, Logger
).
@Component({
selector: 'dropdown',
template: `Dropdown using {{this.logger.getName()}}`
})
export class DropDownComponent implements OnInit {
@Input() public logger: Logger;
constructor() { }
ngOnInit() {
console.log(`DropDown, I'm using `, this.logger.getName());
}
}
2- In the component that uses the drop down then define the value for the logger
property.
@Component({
selector: 'my-app',
template: `
<dropdown [logger]="this.logger1Service" ></dropdown>
<br />
<dropdown [logger]="this.logger2Service" ></dropdown>
`
})
export class AppComponent implements OnInit {
constructor(
public logger1Service: Logger1Service,
public logger2Service: Logger2Service
) { }
ngOnInit() {
console.log('Hello from AppComponent');
console.log('calling logger1Service.info() with message X', this.logger1Service.info('X'));
console.log('calling logger2Service.info() with message Y', this.logger1Service.info('Y'));
}
}
3- And define the services that could be provided for this dropdown.
// logger.interface
export interface Logger {
info(text: string);
getName();
}
// logger1.service
import { Injectable} from '@angular/core';
import { Logger } from './logger.interface';
@Injectable({ providedIn: 'root' })
export class Logger1Service implements Logger {
constructor() { }
info(text: string) {
console.log('Logger 1:', text);
}
getName() {
return 'Logger1Service';
}
}
// logger2.service
import { Injectable} from '@angular/core';
import { Logger } from './logger.interface';
@Injectable({ providedIn: 'root' })
export class Logger2Service implements Logger {
constructor() { }
info(text: string) {
console.log('Logger 2:', text);
}
getName() {
return 'Logger2Service';
}
}
Upvotes: 3
Reputation: 602
It's better to wrap this dumb component into container and reuse it. You smart component will inject service with specific interface. The service you can declare in the parent component to container.
I created stack blitz demo
Upvotes: 0