Reputation: 972
Let's say we have an application with a lot of lists and therefor some basic components
export class SimpleListComponent { ... }
export class ExtendedListComponent extends SimpleListComponent { ... }
... which we can easily extend. They carry all the basic functionality for our lists (e.g. switch pages, count results,...). We use those two basic components for two different lists of heroes:
export class HeroSimpleListComponent extends SimpleListComponent { ... }
export class HeroExtendedListComponent extends ExtendedListComponent { ... }
Unfortunately we still would have to duplicate a lot of our code because HeroSlimListComponent
and HeroExtendedListComponent
share a lot of their functionalites (e.g. load heroes, route to hero, ...).
My first try was to pass the class which we need to extend
export class ExtendedListComponent<T = SimpleListComponent> extends T { ... }
but that does not work. Additionally I found this post which states, that multiple inheritance is not possible within typescript. Still I have the feeling that I'm missing some basic angular component connected solution here.
Thanks in advance for your help!
Upvotes: 2
Views: 3016
Reputation:
You are correct, multiple inheritance is not a thing available (unfortunately because it'd be super cool).
Possibility 1 It seems like your common actions could live inside of the simple list component and you could provide the properties needed in the extending components (like paths) in the constructor. When you call super(), the config options can be passed down.
export class SimpleListComponent {
constructor(
routePath: string,
) {}
}
// extending component
export class HeroSlimListComponent extends SimpleListComponent {
constructor() {
super('<my-route-path>');
}
}
Possibility 2 It might be worth checking out mixins! I have not played with these though, so maybe someone with some experience can weigh in? They don't seem like they'd fully solve the problem as you still have to implement the interface, but it could be a good common set of functionality for the parent components.
Possibility 3 (possibly my personal fav) Keep the generic list and extended list components as components that accept inputs and give outputs and don't extend them. Instead, use them in html. For example, navigation paths can be passed in, and data services can be provided at the parent level component and injected into the child components in the tree. To configure the list items, you can pass in template refs (see the material tables examples). This is just a rough example and would need optimization, but here you go:
// simple list component
// selector = simple-list
constructor(simpleListService: SimpleListService) {}
// hero simple list component
@Component({
....
providers: [
{ provide: SimpleListService, useClass: HeroSimpleListService },
],
})
// html
<simple-list [navPath]='heroNavPath' <...other templates / props>>
Something to keep in mind is that every piece of code from a class you extend is added again to your final build as duplicated code in each extending component (check out the output from prod builds, it's kinda interesting).
Upvotes: 1