Closed richardtallent closed 7 years ago
I cannot reproduce your issue with the following example:
<template>
<table style="width:100%">
<thead></thead>
<tbody></tbody>
<tfoot>
<tr>
<td colspan="10">
<resize-sensor @resize="onResize"></resize-sensor>
</td>
</tr>
</tfoot>
</table>
</template>
<script>
export default {
components: {
resizeSensor: require('vue-resize-sensor')
},
methods: {
onResize: function(size) {
console.log('resize', size);
}
}
}
</script>
I'm using display:flex
on the table so I can scroll the tbody (which is why I need resize events--to sync the column header widths). Not sure if it's related to the issue. I haven't had time to construct a minimal test case yet.
I found two root causes in my case:
If any ancestor of resize-sensor has display: none
when the app is mounted, the resizer doesn't work, even after the display style is changed back to "block". (I set my div#app
to display:none
to avoid FOUC before Vue mounts it.)
If any ancestor of resize-sensor is changed to display: none
, it no longer detects resizing. This I suppose makes sense, but makes it more difficult to use in a context like a table, where I don't really want a footer.
For both of the above, using visibility:hidden
or height:0 !important
works around the issue, but I may not always have control over (1) (for example, if the sensor is in a hidden modal dialog component).
There's also some weird issue related to parents using display:flex
and the if ( this.$el.offsetParent !== this.$el.parentNode )
line, but I can't seem to nail it down enough to give an example.
Yup, there's a problem with the line mentioned above when resize-sensor
is placed in a flexbox table's tfoot's td -- the changing of the td's position to "relative" is the culprit. I'm a little over my head in the CSS, I can see the TR in that case doesn't extend across the row, which may be related.
Hi Richard,
One important point is that the container of the resize-sensor
must be positioned (absolute, relative, ... anything except static) on order to allow the resize-sensor
to occupy the whole space of its container (see position: absolute; left: 0; top: 0; right: 0; bottom: 0
style).
For point (1), I can send an initial resize event when the component is mounted but think it is not possible to detect the case when an ancestor changed from display: none
.
I was really hoping to not needlessly wrap my table component in another DIV, but I suppose that's the best way to get resize-sensor
away from the weirdness of a flexbox table.
For (1), this is unfortunately an area where Vue's "props down, events up" approach fails -- not every important event is detectable at the child or dependent on a property. It's quite common to have components that are mounted but not displayed when the page is loaded (tabs, dialogs, etc.).
I can use the global bus to have elements that have hidden states (like tabs and modals) emit a message to any component with a resize sensor, and those components could then tell their resize sensors to reset, but I would feel "wrong" calling the resize sensor's mount() -- might be better for the setup logic to be extracted to another method so it isn't so tightly coupled to the lifecycle event.
I think that flexbox is not an issue. The real issue is when the resize-sensor
become visible after its creation. I think that my resize-sensor
component should handle any borderline case by itself. The props down, events up model can really help you to keep big webapp consistent and modular.
I have added an event-based visibility detection (for modern browsers only (IE10+), fallback will poll). Please check v1.0.5
ping!
I got distracted by other tasks and didn't get a chance to try it yet. I'll give it a shot!
Looks like it's working now, thanks!
Good !
I have something like the following in my table component:
And in my methods:
The table resizes with the window, but
onResize
never fires. By adding other log statements directly toresize-sensor.vue
, I can tell that themounted
fires, butscroll
never does. I can also confirm via F12 tools that the resize sensor's template is being rendered properly in the DOM.Placing the resize-sensor outside of the table inside the div that wraps it had no effect either. Not sure what to do to test this further.