Right now, I have dead simple use case of the inheritance, but for the life of me, I cannot get it to work.
The use case
My use case is thus:
- I have
BaseComponentthat has someLoaderComponent. It has methodsshowLoader()andhideLoader()for showing it and hiding it, respectively. - Every loadable component, or even every component, extends this
BaseComponent. Then, when there is network request, or we need to wait for a lot of stuff to render, we can justshowLoader(), and thenhideLoader()when the work is done.
Implementation
My implementation of this is pretty straightforward, but for some obscure reason, it's not working.
base.component.ts
//...
export class BaseComponent implements AfterViewInit {
@ViewChild(LoaderComponent) loader: LoaderComponent;
constructor() {}
ngAfterViewInit() {
// caveman debugging, I know. Even worse is that I found myself placing breakpoint on this line of caveman debugging. SAD!
console.log(this.loader);
}
showLoader() {
this.loader.show();
}
hideLoader() {
this.loader.hide();
}
}
base.component.html
I use transclusion here, of course.
<ng-content> </ng-content>
<app-loader #loader></app-loader>
contact.component.ts
//...
@AutoUnsubscribe
export class ContactComponent extends BaseComponent implements OnInit {
constructor(
private senderService: SenderService,
private messageSentService: MessageSentService,
private router: Router
) {
super();
// setup logic here...
}
ngOnInit() {}
sendEmail() // or whatever...
{
this.showLoader();
// send the email
// do the request
this.emailSender = this.senderService.send(this.emailMessage);
this.emailSender.subscribe((res) => {
this.hideLoader();
// handling the request here....
}
//...
}
contact.component.html
<app-base>
<!-- the contact page -->
</app-base>
When I fire this up, what I see, in the developer console, is :
.
When I place my breakpoint on the caveman debugging in BaseComponent.prototype.ngAfterViewInit(), it hit twice. On the first instance, I get this.constructor.name === "BaseComponent". However, on the second one, is the derived class : this.constructor.name === "ContactComponent".
The state of the decorated view child field loader isn't being passed down!!
How do I fix this, and without resorting to some bullshit design like making the derived class has-a base class?

contact.component.htmldoesn't have an<app-loader>as far as I can tell.templateand specify its own template, and b) Angular is a terrible framework for DRY. Angular is absolutely stuffed to the gills with requirements to write redundant boilerplate and often straight-up duplicate code.