Vuetable-2: Responsive table using bootstrap

Created on 10 May 2018  路  5Comments  路  Source: ratiw/vuetable-2

Hi to all,
I've started working with the next branch and I've seen that there are some issues in those days about some way to make the tables responsive #356 , so I want to share my point of view of that argument, hoping that could help.
I'm trying to apply the responsive class bootstrap use, that need some css properties a little bit different from the one that is used now, and so it doesn't work:
In bootstrap, the table use the normal behavior of an html that autosize the column based on the largest content in that column, and then use a wrapper with the scroll, that contains all the table.

I've seen that actually you have forced the "table-layout: fixed" on the table, making impossible to use that trick bootstrap use for the responsiveness of the table. Also, doing that, a table with many columns (like 7 or more) become unusable in portrait mode of a smartphone (all the column in compressed in a width of 300px), and the only way to have something decent is set the width of all the column. But setting the width to a fixed value, can due to other problem, like unwanted line break, that the normal behavior of the table manage.

Finally, I've seen that now the header of the table is placed in a component outside the table, and there isn't a way, like before, to switch between having another table and having the th in the original table.
I can understand that those setup is useful for doing the fixed header, but for who don't wont that, and prefer to have all the row in the same table, there isn't a way now.
Personally I don't like to have those row outside of the main table, for two reason:

  • You are forced to use fixed table or fixed cell width , otherwise the two table table couldn't be aligned (or autosized)
  • You have to sync the horizontal scroll of two items with javascript, while there can be in a single container that can scroll all the content (and the movement is smoother)

In a previous issue, you have said that this component is css framework agnostic, but forcing those behaviors currently that's not true, because I can't apply my own style to the table.
I would suggest to revert using a v-if on the header component, so we can switch between an external table or the thead/th component inside the table. Also I would suggest to make ALL the css class controllable with the props:
Actually some style is applied to some class that is hardcoded in the component, and we can't remove (like the one for vuetable-head-wrapper/vuetable-body-wrapper, or table.vuetable)

I think that those two suggestion could help open to more way of working with the component, adding some options, and wouldn't exclude the current behavior, but open to other way to style the table.
Also that doesn't exclude the detail-row proposal that was done (#438 )... you have simply to toggle the visibility of some column, and the table would auto-adapt... Using bootstrap, you could do that applying the hide utilities to the column cells (for example, .d-none.d-table-cell-md would only show the columns with a resolution >= md). That is less perfect than calculate when a column is outside of the table, but could do the trick, without javascript calculation.

Backing to the two suggestions, If could be helpful I would like to try to code that and send a PR to review on the next branch ;) Otherwise, let me know if there is some other way/trick to apply to have the behavior I'm trying to reach :)

Thanks
Cheers Mix

Most helpful comment

@mix359 Thank you very much for your input.

This is also one of my concern in going all in with fixed header. So, I decided that I would ask for opinion on this when I release the "v2.0 beta" to gather some thought before actually push it to the master branch. Currently, I'm trying my best to finish the documentation for reference.

However, you've given a very detail explanation already and I think they are valid enough to put back v-if into the template, so that the developer has the option to either use the normal table or split table that support fixed header. I'll just have to find time to do it then.

For issues with CSS, I think it should be easy to override the hard coded classes but I forgot that I use scoped in the style section that cause some difficulty in override those css classes.

Also, css classes like vuetable-head-wrapper/vuetable-body-wrapper (and some others) are necessary for styling the fixed header properly. This has to be investigated a little further as the v-if for single table will be added back.

The suggestion from #438 was nice but it must be optional and should be implemented as a row plugin. This will be possible in v2.1 when Row Component is introduced.

It would help a lot if you could set up one or more CodeSandbox project to demonstrate the bootstrap table you mentioned in pure HTML, so I can have a guide to check with Vuetable's code. But you're also welcome to send any PR or review on the next branch. Any input is really appreciated.

All 5 comments

@mix359 Thank you very much for your input.

This is also one of my concern in going all in with fixed header. So, I decided that I would ask for opinion on this when I release the "v2.0 beta" to gather some thought before actually push it to the master branch. Currently, I'm trying my best to finish the documentation for reference.

However, you've given a very detail explanation already and I think they are valid enough to put back v-if into the template, so that the developer has the option to either use the normal table or split table that support fixed header. I'll just have to find time to do it then.

For issues with CSS, I think it should be easy to override the hard coded classes but I forgot that I use scoped in the style section that cause some difficulty in override those css classes.

Also, css classes like vuetable-head-wrapper/vuetable-body-wrapper (and some others) are necessary for styling the fixed header properly. This has to be investigated a little further as the v-if for single table will be added back.

The suggestion from #438 was nice but it must be optional and should be implemented as a row plugin. This will be possible in v2.1 when Row Component is introduced.

It would help a lot if you could set up one or more CodeSandbox project to demonstrate the bootstrap table you mentioned in pure HTML, so I can have a guide to check with Vuetable's code. But you're also welcome to send any PR or review on the next branch. Any input is really appreciated.

@ratiw I'm sending you a PR with some small modification I've started to do:

  • I've replicated the thead block and made conditionally exclusive using the isFixedHeader
  • I've added a fixed-header css class to the table that is activated using the isFixedHeader as a condition
  • I've added the fixed-header to the css rule that contains the "table-layout: fixed;", in this way is only used when the table is in fixed header mode
  • I've added a watch to the fields props to make possible the change of the columns even after the table creation. I haven't talked about that in this issue, but I need to hide some column and modify some data after the table creation. If it's a problem, I can take that code away, but from my test it completely work, and open to new possibilities (like enabling/disabling columns)

In this way I've fixed the issue I was having with the double table and the fixed layout. The only thing that remain unsolved is a conflict between the style done by the vuetable-body-wrapper and the table-responsive class of bootstrap that create the responsiveness of the table.
They both work in a similar way (using the overflow-x: hidden) but the table-responsive class of bootstrap have some other options (like the one for the touch) and can be used with the responsive step (you can for example use table-responsive-sm and in this way the overflow: hidden in applied only on screen with less then 768px).
The default behavior of bootstrap doesn't use the overflow: hidden, you can add it if you need it, but currently the style in vuetable-body-wrapper are forcing it.
If is absolutely needed for the fixed header table, a solution could be to make even that css rule based on the .fixed-header class, so it's only used in that case (like I've done with the table.vuetable css rule).
In that case, if is not a problem, I would like to add some other css options to the $_css props, like bodyWrapperClass or theadClass to add custom class from outside, so I can re-add the table-responsive class.

In general, I haven't touched the other css that are in the main component, because it's a little confused:
Some of that is useful to make the layout of the component (like the one for the fixed header), some other, like the vuetable-actions class, seam only a possible way to style it, also, many of the class added by the CssSemanticUi.js is useless in a framework like bootstrap.
So I'm thinking that would useful to divide the style from the logic of the component in some way, like having a theme file. So if someone need to use the component as-is, it can load the default theme, that have his css classes (the one that come from CssSemanticUi) and his css rules.
In this way you can also ship the component with the theme for some other framework.
The best would be to not have any css rule in the component area, at least is really needed by the component to work.
What do you think of that?

About the html of bootstrap table on CodeSandbox I will try to find a little bit of time to make that, but in general is really simple and well documented here, but if you need that I can make it.
In general is nothing more that this:

<div class="table-responsive">
<table class="table">
  <thead>
    <tr>
      <th scope="col">#</th>
      <th scope="col">First</th>
      <th scope="col">Last</th>
      <th scope="col">Handle</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">1</th>
      <td>Mark</td>
      <td>Otto</td>
      <td>@mdo</td>
    </tr>
  </tbody>
</table>
</div>

Thanks for all
Cheers Mix

@mix359 Many thanks for the PR. Really appreciate it.

I'm still can't find the time to check it in detail. I need to spend time checking it against other examples that use Semantic UI first.

For "watch fields", I think it might need another prop, e.g.reactive-fields, to make it explicit as it changes behavior from the previous version and it might caught people off-guard.

Based on what you've described in term of Bootstrap CSS, I think I got it. Since my CSS knowledge is quite limited mostly to Semantic UI, your explanation helps a lot.

Initially, the css with vuetable- prefix is intended to give each section in Vuetable (at least) a class to allow people to style it. But Vuetable has changed a lot and I may have unintentionally use it to fix problems with fixed header styling, that it gets quite confusing.

So, it should be reverted back to its original purpose and remove any specific styling that would cause problem in other CSS framework.

The CssSemanticUI.js is intended to be a central place to modify style for Vuetable to be able to use with other CSS framework. It is enough for Semantic UI, but might not be enough for other CSS framework.

But I hope that when this v.2.0-beta is released, I would get feedback like yours to help improving it. I hope that when it is solid enough, people would publish this file on NPM and the others can pull in and just assign it to css prop.

Here is one for Bootstrap 4, which also utilizes FontAwesome for the icons.

I think this is the minimum CSS classes that will be remained.

<!-- for Normal table -->
<div class="vuetable-wrapper" :class="css.tableWrapperClass:>

  <table class="vuetable" :class="css.tableClass">
    <colgroup></colgroup>
    <thead :class="css.tableHeaderClass"></thead>
    <tfoot :class="css.tableFooterClass"></tfoot>
    <tbody :class="css.tableBodyClass">
      //...
    </tbody>
  </table>

</div>
<!-- for Fixed header table -->
<div class="vuetable-wrapper" :class="css.tableWrapperClass:>

  <div class="vuetable-head-wrapper">
    <table class="vuetable" :class="css.tableClass">
      <colgroup></colgroup>
      <thead :class="css.tableHeaderClass"></thead>
    </table>
  </div>

  <div class="vuetable-body-wrapper">
    <table class="vuetable" :class="css.tableClass">
      <colgroup></colgroup>
      <tfoot :class="css.tableFooterClass"></tfoot>
      <tbody :class="css.tableBodyClass">
        //...
      </tbody>
    </table>
  </div>

</div>

The rest is mostly related to icon rendering and sorting state, which are there only because I want them to be in a single place. Feeling weird that they are there, but still don't know where else to put them.

@mix359 Just published v2.0.0-alpha.22 on npm. Can you please help checking if any other problem in your work?

Sorry @ratiw, yes I'm working with that version and it all seam to work for me.
I'll let you know in the next day if there's something that give me problem, and when I have a little bit of time, I would dig into the css story, to see if I can think something useful to suggest ;)
Thanks
Cheers
Mix

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kawamataryo picture kawamataryo  路  3Comments

larryu picture larryu  路  6Comments

mondul picture mondul  路  3Comments

coderabsolute picture coderabsolute  路  4Comments

jdriesen picture jdriesen  路  4Comments