angular / components

Component infrastructure and Material Design components for Angular
https://material.angular.io
MIT License
24.37k stars 6.75k forks source link

[Table] Responsive stacking support #8494

Open marcusreese opened 6 years ago

marcusreese commented 6 years ago

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.,

     Header 1     Header 2     Header 3     Header 4
       1.1          1.2          1.3          1.4
       2.1          2.2          2.3          2.4

becomes

     Header 1        1.1
     Header 2        1.2
     Header 3        1.3
     Header 4        1.4

     Header 1        2.1
     Header 2        2.2
     Header 3        2.3
     Header 4        2.4

and even

     Header 1
        1.1
     Header 2
        1.2
     Header 3
        1.3
     Header 4
        1.4

     Header 1
        2.1
     Header 2
        2.2
     Header 3
        2.3
     Header 4
        2.4

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 image

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.

alexzaytsev-newsroomly commented 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).

mhosman commented 6 years ago

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?

andrewseguin commented 6 years ago

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: sdgmds2pcop

Narrow-screen: nuamqoyocjs

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

dhniels commented 6 years ago

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.

imVinayPandya commented 6 years ago

@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.

liluxdev commented 6 years ago

1+ for responsive table

ayepiz commented 6 years ago

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.

mhosman commented 6 years ago

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.

budkin76 commented 6 years ago

Another +1 for built-in responsive Angular Material Tables

Adiel-Sharabi commented 6 years ago

1+ for that!

Dando1996 commented 6 years ago

Has angular added support for this yet?

JoniJnm commented 6 years ago

Is there any way to add the mobile-label programmatically?

kjvdven commented 5 years ago

I use it like this, don't remember anymore what is my code and what I copied. https://stackblitz.com/edit/rman-2952

ghost commented 5 years ago

One more, +1 for this feature.

jelbourn commented 5 years ago

(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.

b-mi commented 5 years ago

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.

b-mi commented 5 years ago

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.

nickykapur commented 5 years ago

+1 for responsive mat table

iameduardod commented 4 years ago

@angular any update?

b-mi commented 4 years ago

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.

knoefel commented 4 years ago

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:

Here 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.

b-mi commented 4 years ago

knoefel, nice work. Another way is hide some columns according to display width.

andreElrico commented 4 years ago

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)

πŸš€ πŸš€ πŸš€

please note:

How to start

1 add the the directive to mat-table <table mat-table [responsiveTableWithTpl]="respPattern" responsiveTableAtPx="360" ...

  1. add styles to global. Took inspiration here: >> (StackB)

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.

Things to do

sathishvisar commented 4 years ago

I created little sample for material table responsive.

datatable-responsive

Stackblitz Example

b-mi commented 4 years ago

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.

eddiesri commented 4 years ago

I created little sample for material table responsive.

datatable-responsive

Stackblitz Example

Thank you so much, this is really helpful

b-mi commented 4 years ago

eddiesri - yes - this is really responsive table!

b-mi commented 4 years ago

Every row could have its actions - edit / delete / run function - how to do this?

vincentsels commented 4 years ago

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;
  }
}
ganeshsundaram39 commented 3 years ago
<div class="table-responsive" >   
    <mat-table
          [dataSource]="items"
          style=" overflow: auto ;
          display: table-cell;
          width: 100vw;"
    >
    </mat-table>
</div>
mrmokwa commented 3 years ago

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.

dhammond371 commented 2 years ago

It would be great to have an official material version like the solution by @andrewseguin.

kfw9257 commented 2 years ago

Any updates on an official responsive stacking solution?

Saytzeff-D commented 2 years ago

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

CarlosBustos1 commented 8 months ago

Is there any updates on this features? It would be fantastic