Open marcusreese opened 6 years ago
I was able to implement a workaround using samples provided here: https://css-tricks.com/responsive-data-tables/
It would certainly be nice to be able to have this behaviour as part of the component (and toggle it on/off).
Agree with @marcusreese, this is a must-have feature in a first-mobile & across devices today's world. Maybe some workaround with FlexLayout as an example?
Since the foundation of the table allows for any arbitrary content to be in the header/row cells, it'll be hard to make a universal approach. For example, if your header has a filter/menu/icon/etc then you'll likely not want those things to show up in the responsive version.
I'll incorporate this into my design for some kind of mat-simple-table
which understands more deeply about what data is being shown and some rules on what is possible (e.g. header cells are only text).
For now with the current tables, it's just too open for any templates to fully prescribe something.
That said, if you want to make your tables responsive. Here's an example of how you can do this:
Wide-screen:
Narrow-screen:
CSS:
// By default, the mobile label shouldn't show
.mobile-label {
display: none;
}
@media(max-width: 600px) {
// Custom header label that shows in each column, with a set width and bold font
.mobile-label {
width: 80px;
display: inline-block;
font-weight: bold;
}
// Remove the header row altogether
.mat-header-row {
display: none;
}
// The row cells should display as a column, justified left, with a bit of extra padding
.mat-row {
flex-direction: column;
align-items: start;
padding: 8px 24px;
}
}
Here's a working example: https://stackblitz.com/edit/angular-mohmt5?file=app%2Ftable-basic-example.ts
Some sort of responsive implementation would be nice, even at the very least allow the table to overflow along the x-axis and perhaps add a fixed column. For example, there is a Vue.js component library called Element that has a lot of nice options for table. Check out an example at Element's website.
@dhniels I think that is an awesome idea. that table's functionality looks awesome. I hope that material team will provide these kinds of options.
1+ for responsive table
I think a scroll at the x-axis will be a great approach and of course, it will be a lot better if an implementation of a fixed column like the Element's webpage is added.
Another simple workaround to make the table responsive:
Create a new div:
<div class="responsive_table">
</div>
Inside that div create your mat-table. Now go to your css and put something like this:
@media(max-width: 800px) {
.responsive_table {
overflow-x: auto !important;
}
.mat-table {
min-width:800px;
}
}
This is not an "elegant" solution but works.
Another +1 for built-in responsive Angular Material Tables
1+ for that!
Has angular added support for this yet?
Is there any way to add the mobile-label
programmatically?
I use it like this, don't remember anymore what is my code and what I copied. https://stackblitz.com/edit/rman-2952
One more, +1 for this feature.
(I'm going through the highest voted issues today an commenting on their status)
We currently don't have any active plans to work on this; the cdk-table/mat-table adheres pretty strictly to the single-responsibility principle, where that responsibility is "render rows of cells". You can see this in the way that sorting and pagination are enhancements added on top of the table without being built into it. Switching to a different rendering structure based on screen-size seems just outside of that responsibility.
That said, we do want to provide some guidance (and maybe some components) at some point to help make this interaction easier, even if it's not built directly into the table. This definitely won't happen in 2019, though.
I use it like this, don't remember anymore what is my code and what I copied. https://stackblitz.com/edit/rman-2952
Thanks, thats the first and only way - which I found on internet - how to make table (not mat-table) responsive. But it is visible how hard it is - label has to be hardcoded two times, and that way which doesn't allow align data-label left and data right. Or is it possible?
There are more examples for making mat-table responsive. But material table is now declared by table element, not mat-table element. So these examples do not work for actual material table. I will appreciate if actual material table responsivity has working example in official material documentation.
What is the reason for the existence of both mat-table and cdk-table? It brings ambiguities and complications. But it seems that the material schematic for a table wants to support cdk-table using a DataSource that does not have a filter like MatTableDataSource. DataSource brings nothing useful, just complications and complexity where it should not be. I suggest that Material has one component for the table and that it has completed properly - and this component should by supported by material table schematic generated component. I spend my days solving these ambiguities.
+1 for responsive mat table
@angular any update?
We at last solve this by reduction of visible columns according to display sizes and displaying rest columns in grid detail. Change material table row into column is not very good solution.
I created a little directive which can be applied to a mat-table
table to make it responsive. This way it is easy to only add responsive behavior to only some tables in the application (which was a requirement in my case). So basically the directive duplicates the content of each header cell (column name) as an data attribute so it can be accessed via the CSS content
property (inspired by the link from the first comment in this thread). Unfortunately CSS styles can't be applied to a directive, so the styles need to be imported globally.
Features:
matSort
directiveHere is a little stackblitz demo:
https://stackblitz.com/edit/material-table-responsive
This should not be seen as a general solution, as it does of course not cover all use cases. Also the styling of the table mobile view is bound to my specific requirements and probably needs to be adjusted. But maybe it helps/serves as a starting point for others.
knoefel, nice work. Another way is hide some columns according to display width.
I have created a responsive solution for the matTable that I believe is currently the best that I know of.
π π π (make sure you use dev-tools "mobile/tablet"-view mode + "responsive" to minimize the window width)
https://stackblitz.com/edit/responsive-mat-table-monkeypatch
https://stackblitz.com/edit/responsive-mat-table-monkeypatch-multicutoff (version with 2 cutoffs like OP suggests)
π π π
please note:
ExpressionChangedAfterItHasBeenCheckedError
is due to this line : <p> Table width {{ t1._elementRef.nativeElement.offsetWidth }} px </p>
that shows you the current width of the table. I think its nice to have this on display.
The transition from NORMAL to STACKED (and vise versa) might seem "slow/ clunky". Its due to fromEvent(window, "resize") .pipe(debounceTime(400))
this can be changed ...
How to start
1 add the the directive to mat-table
<table mat-table [responsiveTableWithTpl]="respPattern" responsiveTableAtPx="360" ...
respPattern
is the "template" for how the stacked version should look
responsiveTableAtPx
defines the cutoff in pixels when the table should transform.
thats it.
Implementation details
By looking at the source of cdk-table (and I tell you its a very complex ...) I figuered that _renderRow()
is a very essential function to render the table. So the idea is to "monkeyPatch/ duckPunch" this function to make use of my "respPattern" ng-template
@jelbourn @andrewseguin If the material-team would provide some api to add a customRenderRow() this issue could be closed.
matTable.customRenderRow(myFun1)
and for native render matTable.customRenderRow(null)
this.matTable._forceRenderDataRows();
when I transform the table since the "data-model" did not change ...Things to do
better api ?
better css to make it look like here? StackB
we are observing window:resize
could we observe the width change of nativeElement-MatTable?
If the table width changes that is not due to window-resize we have to currently manually call <responsiveTableWithTpl>.onResize()
.
I created little sample for material table responsive.
sathishvisar - very nice - your solution hides columns by the width of the display, and allows you to show the hidden columns at the click of a button.
I have one suggestion - now, the table hide the last column by the size of the display. It would be better to allow for each column from which display width to display, e.g. showIfWidthAbove: "xs" for an important column that always appears, showIfWidthAbove: "md" if the display width is 960px or more. This is because it is usually necessary to have the columns in the table in a different order than the hiding order. This would really be a solution for a real application.
I created little sample for material table responsive.
Thank you so much, this is really helpful
eddiesri - yes - this is really responsive table!
Every row could have its actions - edit / delete / run function - how to do this?
To get @andrewseguin 's fantastic solution to work on Angular Material 8, I had to unset a couple of css properties on .mat-row
and mat-cell
. Here's the new code:
// By default, the mobile label shouldn't show
.mobile-label {
display: none;
}
@media(max-width: 600px) {
// Custom header label that shows in each column, with a set width and bold font
.mobile-label {
width: 80px;
display: inline-block;
font-weight: bold;
}
// Remove the header row altogether
.mat-header-row {
display: none;
}
// The row cells should display as a column, justified left, with a bit of extra padding
.mat-row {
flex-direction: column;
align-items: start;
padding: 8px 24px;
min-height: unset; // Tweak for Angular Material 8
}
// Tweaks for Angular Material 8
.mat-cell:first-of-type, .mat-footer-cell:first-of-type, .mat-header-cell:first-of-type {
padding-left: unset;
}
.mat-cell {
align-items: unset;
min-height: unset;
}
}
<div class="table-responsive" >
<mat-table
[dataSource]="items"
style=" overflow: auto ;
display: table-cell;
width: 100vw;"
>
</mat-table>
</div>
In @andrewseguin example, it's used mat-header-cell and mat-cell classes, etc. Is it possible to achieve the same result, but using native table tags (td, th, tr) instead? I mean, all docs guides are implemented with native tags, (guess) to dynamically change the column size, based on content.
It would be great to have an official material version like the solution by @andrewseguin.
Any updates on an official responsive stacking solution?
We at last solve this by reduction of visible columns according to display sizes and displaying rest columns in grid detail. Change material table row into column is not very good solution.
Exactly, it's not a very good solution at all. Peradventure, there's a way mat-table can be made responsive like bootstrap-table, that would have been the best
Is there any updates on this features? It would be fantastic
Bug, feature request, or proposal:
feature request
What is the expected behavior?
I would like to be able to convert a CDK table into a stacked list. I want to do this through CSS media queries (i.e. when window size is narrow), and I also want to be able to do it through JavaScript (e.g., when the user clicks a button). The header cell contents should be displayed on each line instead of just at the top. E.g.,
becomes
and even
If this is already facilitated by the CDK, I would like to see an example of this feature in the docs.
What is the current behavior?
The two docs pages I am looking at (https://material.angular.io/guide/cdk-table and the link below) do not mention 'responsive' or 'stack', and there are no demonstrations of tables that stack.
From https://material.angular.io/components/table/overview
What are the steps to reproduce?
Go to https://material.angular.io/components/table/overview on a small mobile browser or, with a desktop browser, resize the window to be narrow (e.g., 760px wide).
What is the use-case or motivation for changing an existing behavior?
1) There are groups where I work, and no doubt at many other organizations, that do not want to use a table library that does not offer this feature. 2) The need for this feature is evidenced by its existence in other solutions, such as PrimeNG datatable https://www.primefaces.org/primeng/#/datatable/responsive and https://css-tricks.com/responsive-data-tables/
Which versions of Angular, Material, OS, TypeScript, browsers are affected?
N/A
Is there anything else we should know?
This is a restatement of https://github.com/angular/material2/issues/6608, trying to follow the advice of @jelbourn.