Tengo un formulario que se utiliza para elegir los detalles del cliente. Se usa en más de un lugar en mi aplicación, pero con lógica e interfaz de usuario extendidas. Me gustaría poder reutilizar mi componente básico en otros componentes, pero también extender (o anular) su plantilla y lógica. Para no tener que copiar y pegar la misma interfaz de usuario y lógica en cada componente y tener un lugar básico común para los cambios.
componente base con plantilla y lógica:
@Component({ selector: 'app-base', template: `<h1> Base component </h1> <label>getLabel() </label> <ng-content> </ng-content> ` }) export class BaseComponent implements OnInit { constructor() { // base init } ngOnInit(): void { // base ngOnInit } getLabel(): string { return "label"; } }Componente principal que se supone que reutiliza la plantilla, pudiendo extender métodos y ganchos de vida y también extender la interfaz de usuario.
@Component({ selector: 'app-parent', template: `<app-base> <h1> extended </h1> </app-base>`, }) export class ParentComponent extends BaseComponent { constructor() { super(); } ngOnInit(): void { super.ngOnInit(); // extended fancy stuff } getLabel(): string { let a = super.getLabel(); return a + "a"; // extended logic } }Funciona con este enfoque, pero un problema que noté es que ngOnInit se llama dos veces. Una vez desde el componente base ya que estoy usando su plantilla en el componente principal y la segunda vez debido a que se activó parentComponent ngOnInit.
Pregunta : ¿Hay alguna manera de reutilizar la plantilla como usar <app-base></app-base> con toda la lógica compartida en un solo lugar pero sin ejecutar los lifehooks dos veces desde ambos componentes?
Solución (?): Lo único que se me ocurrió es envolver la lógica del componente básico con un servicio. Entonces habrá algo como esto:
@Component({ selector: 'app-base', template: `<h1> Base component </h1> <label>getLabel() </label> <ng-content> </ng-content> `}) export class BaseComponent implements OnInit { constructor(IBasicService basicService) { // <-- injected service // base init } ngOnInit(): void { this.basicService.onInit(); // <-- using ngOnInit from service // base ngOnInit } getLabel(): string { return this.basicService.getLabel(); <-- using getLabel from service } }Con este enfoque, podré simplemente reutilizar mi componente base pero con diferentes servicios inyectados que implementarán la interfaz IBasicService y también simplemente extenderán la interfaz de usuario usando o pero es esta forma correcta? ¿No hay ninguna solución mejor?
¡Gracias por adelantado!