angular-datatables
angular-datatables copied to clipboard
ngTemplateRef does not work on responsive windows-mode when columns are stacked
:beetle: bug report
When I use the responsive extension, it only shows the plain text from the source and not the template-version if the windows size is in responsive mode. Back in full window size mode the template is rendered as expected.
Is there a way to fix my problem with code adjustments or is this a bug? Thanks for the support!
:microscope: Minimal Reproduction
StackBlitz/GitHub Link: https://stackblitz.com/edit/stackblitz-starters-rx7mzq?file=package.json Step-by-step Instructions: Minimize and maximize the window on StackBlitz to see the difference.
:8ball: Expected behavior
The ngTemplateRef column should display the referenced template and not the pure rendered text from the source, in the same way as it displays the content for non-stacked/-responsive views.
:camera: Screenshots
Normal View - component shown:
Responsive - plain data text shown:
:memo: Additional context
see closed issue: https://github.com/l-lin/angular-datatables/issues/1723 columnDefs does not solve the issue with the rendering on responsive mode.
Hi @lingold-gseb
Can you try redrawing the table on https://datatables.net/reference/event/responsive-resize or https://datatables.net/reference/event/responsive-display?
I suspect this happens because responsive plugin resets the transform we apply on the table's cell during init.
Hi @shanmukhateja thanks for the answer! I tried to redraw the table on the suggested events, but it has no effect on the correct rendering of the templates in responsive mode. See ngAfterViewInit-method in https://stackblitz.com/edit/stackblitz-starters-yg83ku?file=src%2Fexample%2Fexample.component.ts
dtInstance.on(
'responsive-resize',
(e: any, datatable: any, columns: any) => {
const count = columns.reduce((a: any, b: any) => {
return b === false ? a + 1 : a;
}, 0);
console.log(count + ' column(s) are hidden');
dtInstance.draw();
console.log('called draw()');
}
);
});
Is there a mistake in my implementation of the redraw-approach or do you have another idea how to solve the problem? A thought perhaps: If the page is initially loaded in a minimized responsive window, the elements already will not load correctly.
Thanks!
@lingold-gseb Hi sorry for the late reply.
~~In that case, could you try dtTrigger.next()
instead of dtInstance.draw()
?~~
The goal is to force a redraw of the table.
I think we need to investigate a way to use something like "before cell draw" callback (if it exists) and trigger our custom transformations for TemplateRef
or Pipe
.
Edit: I spent a few hours on this and I believe I have a solution. Are you comfortable with compiling the library locally?
// Replace the function with the same name inside "src/angular-datatables.directive.ts"
private applyNgRefTemplate(row: Node, columns: ADTColumns[], data: Object): void {
// Filter columns using `ngTemplateRef`
const colsWithTemplate = columns.filter(x => x.ngTemplateRef && !x.ngPipeInstance);
colsWithTemplate.forEach(el => {
const { ref, context } = el.ngTemplateRef;
// get <td> element which holds data using index
const i = columns.filter(c => c.visible !== false).findIndex(e => e.id === el.id);
let cellFromIndex = row.childNodes.item(i);
// Responsive plugin messes with table columns
// The code below will trigger when `rowChild` is about to be initialized.
if (!cellFromIndex && this.dtOptions.responsive) {
try {
const rowChildParent = this.dt.row(row).child();
if (rowChildParent) {
// now we need to locate the <td> which has the matching column index
const objListFromIndex = rowChildParent.first().find(`*[data-dtr-index="${i}"]`)?.find('.dtr-data');
if (objListFromIndex.length > 0) {
cellFromIndex = objListFromIndex.get()[0];
}
}
} catch (ignore) {}
}
// reset cell before applying transform
$(cellFromIndex).html('');
// render onto DOM
// finalize context to be sent to user
const _context = Object.assign({}, context, context?.userData, {
adtData: data
});
const instance = this.vcr.createEmbeddedView(ref, _context);
this.renderer.appendChild(cellFromIndex, instance.rootNodes[0]);
});
}
Let me know if this works :)