I want to display some custom component/html between two rows on click. I believe the quick and easy solution would be to use the event from the click handler and manipulate the DOM directly however I'd like to do it the angular way if possible.
For inspiration I first looked at this article on extending structural directive. It was of limited use though since *matRowDef
isn't supposed to be used on its own, but in conjunction with other elements as part of the material table. I then went to have a look at the source code directly and tried to mimic the way MatRowDef
extended CdkRowDef
and ended up with this:
@Directive({
selector: '[expandableRowDef]',
providers: [
{provide: MatRowDef, useExisting: ExpandableRowDirective},
{provide: CdkRowDef, useExisting: ExpandableRowDirective}
],
inputs: ['columns: expandableRowDefColumns', 'when: expandableRowDefWhen']
})
export class ExpandableRowDirective<T> extends MatRowDef<T> {
constructor(template: TemplateRef<any>,
viewContainer: ViewContainerRef,
_differs: IterableDiffers) {
super(template, _differs);
}
}
I then simply switched *matRowDef="..."
with *expandableRowDef="..."
, it compiles fine and doesn't fail at runtime.
Where should I take it from here to edit the DOM inside the created mat-row
element?
I had a basic requirement for something similar a while ago, and managed to put something together based off the discussion and broken plunkr on this thread.
It essentially works by creating a custom component using
ComponentFactory
and then using@ViewChildren
to get a list of the table rows, and on click of the selected table row inserts the custom component at the specifiedindex
passing in the row data using@Input
:Template:
Component:
Custom component which gets inserted between the rows:
I have created a basic working demo of this on StackBlitz here. Since this functionality is not officially supported yet, doing it in this way may eventually break down the line, however the Angular Material team does have something similar in the pipeline.