gwinnem / vue-responsive-grid-layout

A draggable, resizable and responsive grid layout, developed with vue3 and typescript.
https://vue-ts-responsive-grid-layout.winnem.tech/
MIT License
65 stars 8 forks source link

Vue2 to 3 migration, infinite width updates #56

Closed vincent-nagy closed 9 months ago

vincent-nagy commented 9 months ago

Expected Behavior

Grid shows up at right width for grid items.

Current Behavior

Grid shows up very small, 3 errors, all 3 exactly the same.

Failure Information (for bugs)

I tried to trace the issue and it seems to be that the width is constantly updating and can't determine a real width. The event layout-ready never happens. If I resize the window, it shows as it should but I get another error, see error 2.

Steps to Reproduce

Please provide detailed steps for reproducing the issue.

            <grid-layout
                    ref="grid"
                    v-show="mounted"
                    :class="[{ 'pre-mounted': postMounted }]"
                    v-model:layout="layout"
                    :cols="{ lg: 2, md: 1, sm: 1, xs: 1, xxs: 1 }"
                    :col-num="2"
                    :row-height="50"
                    :margin="[20, 20]"
                    :is-draggable="true"
                    :is-resizable="true"
                    :vertical-compact="true"
                    :use-css-transforms="false"
                    :responsive="true"
                    :breakpoints="{ lg: 1250, md: 880, sm: 880, xs: 880, xxs: 880 }"
                    @layout-updated="layoutUpdatedEvent"
                    @layout-mounted="layoutMountedEvent"
                    @columns-changed="updateColNum"
                    @breakpoint-changed="() => console.log('breakpoint-changed')"
                    @changed-direction="() => console.log('changed-direction')"
                    @container-resized="() => console.log('container-resized')"
                    @dragend="() => console.log('dragend')"
                    @dragmove="() => console.log('dragmove')"
                    @dragstart="() => console.log('dragstart')"
                    @layout-before-mount="() => console.log('layout-before-mount')"
                    @layout-created="() => console.log('layout-created')"
                    @layout-ready="() => console.log('layout-ready')"
                    @recalculate-styles="() => console.log('recalculate-styles')"
                    @layout-update="() => console.log('layout-update')"
            >
                <grid-item
                        v-for="item in layout || []"
                        :x="item.x"
                        :y="item.y"
                        :w="item.w"
                        :h="item.collapsed ? 2 : item.h"
                        :i="item.i"
                        :key="item.i"
                        :max-w="1"
                        :min-h="3"
                        :class="[
          item.x === 0 ? 'left' : 'right',
          { isCollapsed: item.collapsed },
        ]"
                        drag-allow-from=".widget-title"
                        drag-ignore-from=".add-widget, .widget-control"

                        @container-resized="() => console.log('container-resized')"
                        @drag-event="() => console.log('drag-event')"
                        @move="() => console.log('move')"
                        @moved="() => console.log('moved')"
                        @resize="() => console.log('resize')"
                        @remove-grid-item="() => console.log('remove-grid-item')"
                        @resized="() => console.log('resized')"
                        @resize-event="() => console.log('resize-event')"
                >

Context

Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.

Latest version of vue, vuecompat and this library.

Failure Logs

Error 1 at load: Uncaught (in promise) Maximum recursive updates exceeded. This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself. Possible sources include component template, render function, updated hook or watcher source function.

Promise.then (async)    
  nextTick @ vue.runtime.esm-bundler.js:1755
  Z @ vue-ts-responsive-grid-layout.es.js:4818
  N @ vue-ts-responsive-grid-layout.es.js:4823
  (anonymous) @ vu

Error 2 at resize: Uncaught (in promise) TypeError: Cannot read properties of null (reading 'emitsOptions') at shouldUpdateComponent (vue.runtime.esm-bundler.js:3046:27) at updateComponent (vue.runtime.esm-bundler.js:9061:9) at processComponent (vue.runtime.esm-bundler.js:9008:7) at patch (vue.runtime.esm-bundler.js:8465:11) at patchBlockChildren (vue.runtime.esm-bundler.js:8855:7) at patchElement (vue.runtime.esm-bundler.js:8747:7) at processElement (vue.runtime.esm-bundler.js:8596:7) at patch (vue.runtime.esm-bundler.js:8453:11) at patchBlockChildren (vue.runtime.esm-bundler.js:8855:7) at patchElement (vue.runtime.esm-bundler.js:8747:7) shouldUpdateComponent @ vue.runtime.esm-bundler.js:3046 updateComponent @ vue.runtime.esm-bundler.js:9061 processComponent @ vue.runtime.esm-bundler.js:9008 patch @ vue.runtime.esm-bundler.js:8465 patchBlockChildren @ vue.runtime.esm-bundler.js:8855 patchElement @ vue.runtime.esm-bundler.js:8747 processElement @ vue.runtime.esm-bundler.js:8596 patch @ vue.runtime.esm-bundler.js:8453 patchBlockChildren @ vue.runtime.esm-bundler.js:8855 patchElement @ vue.runtime.esm-bundler.js:8747 processElement @ vue.runtime.esm-bundler.js:8596 patch @ vue.runtime.esm-bundler.js:8453 componentUpdateFn @ vue.runtime.esm-bundler.js:9240 run @ vue.runtime.esm-bundler.js:450 instance.update @ vue.runtime.esm-bundler.js:9290 callWithErrorHandling @ vue.runtime.esm-bundler.js:1671 flushJobs @ vue.runtime.esm-bundler.js:1879 Promise.then (async) nextTick @ vue.runtime.esm-bundler.js:1755 Z @ vue-ts-responsive-grid-layout.es.js:4818 N @ vue-ts-responsive-grid-layout.es.js:4823 (anonymous) @ vue-ts-responsive-grid-layout.es.js:3923 emit @ vue-ts-responsive-grid-layout.es.js:3922 J @ vue-ts-responsive-grid-layout.es.js:4872

gwinnem commented 9 months ago

Hi Vincent. Im not able to reproduce the error you are getting here. Can you please send me the layout data so i can test with the same layout as you.

vincent-nagy commented 9 months ago

Hi @gwinnem, thanks for you quick response. I hope this value is what you are looking for:

[ { "name": "TaskOpener", "widgetId": "taskopener-0", "i": "0", "x": 0, "y": 0, "w": 1, "h": 3, "collapsed": false, "isResizable": false, "moved": false }, { "name": "PostTask", "widgetId": "posttask-1", "i": "1", "x": 0, "y": 8, "w": 1, "h": 8, "collapsed": false, "moved": false, "_h": 8 }, { "i": "6", "x": 0, "y": 3, "w": 1, "h": 2, "name": "CaseManager", "widgetId": "casemanager-5", "collapsed": true, "moved": false, "_h": 8 }, { "i": "8", "x": 0, "y": 5, "w": 1, "h": 3, "name": "CaseManager", "widgetId": "casemanager-7", "collapsed": true, "_h": 8, "moved": false }, { "i": "9", "x": 0, "y": 16, "name": "AddWidget", "widgetId": "addwidget", "w": 1, "h": 2, "isResizable": false, "moved": false } ]

gwinnem commented 9 months ago

Hi Vincent The layout has to confirm to the TLayout type.

export type TLayoutItem = ILayoutItemRequired & { isDraggable?: boolean; isResizable?: boolean; isStatic?: boolean; maxH?: number; maxW?: number; minH?: number; minW?: number; moved?: boolean; }

export type TLayout = ILayoutItem[];

vincent-nagy commented 9 months ago

So if I understand you, the layout changed since the fork and I need to make sure that my layout complies to the TLayoutItem type?

gwinnem commented 9 months ago

True.

vincent-nagy commented 9 months ago

I'm sorry but I don't see what doesn't match the type you describe. I have all the properties from ILayoutItemRequired and all the other properties you mention are optional. I'm not using typescript so I can't import your types.

Created default layout:
[ { "name":"TaskOpener", "widgetId":"taskopener-0", "i":"0", "x":0, "y":0, "w":1, "h":2, "collapsed":false, "isResizable":false }, { "name":"PostTask", "widgetId":"posttask-1", "i":"1", "x":0, "y":2, "w":1, "h":8, "collapsed":false }, { "name":"CaseManager", "widgetId":"casemanager-3", "i":"3", "x":0, "y":6, "w":1, "h":8, "collapsed":false }, { "name":"ExternalMail", "widgetId":"externalmail-4", "i":"4", "x":1, "y":4, "w":1, "h":8, "collapsed":false } ]

To be certain, I added all the optional values as well, but to no avail. [ { "name":"TaskOpener", "widgetId":"taskopener-0", "i":"0", "x":0, "y":0, "w":1, "h":2, "collapsed":false, "isResizable":false, "isDraggable":false, "isStatic":false, "maxH":10000, "maxW":10000, "minH":10000, "minW":10000, "moved":10000 }, { "name":"PostTask", "widgetId":"posttask-1", "i":"1", "x":0, "y":2, "w":1, "h":8, "collapsed":false, "isResizable":false, "isDraggable":false, "isStatic":false, "maxH":10000, "maxW":10000, "minH":10000, "minW":10000, "moved":10000 }, { "name":"CaseManager", "widgetId":"casemanager-3", "i":"3", "x":0, "y":6, "w":1, "h":8, "collapsed":false, "isResizable":false, "isDraggable":false, "isStatic":false, "maxH":10000, "maxW":10000, "minH":10000, "minW":10000, "moved":10000 }, { "name":"ExternalMail", "widgetId":"externalmail-4", "i":"4", "x":1, "y":4, "w":1, "h":8, "collapsed":false, "isResizable":false, "isDraggable":false, "isStatic":false, "maxH":10000, "maxW":10000, "minH":10000, "minW":10000, "moved":10000 } ]

gwinnem commented 9 months ago

The following are wrong props:

  1. name
  2. widgetId
  3. collapsed
  4. moved (this is a boolean value used internally) So no need to use this prop. This will be removed in a later version.
vincent-nagy commented 9 months ago

Thanks for you quick response. These are just properties we use internally, removing them from the data doesn't change the issue we face.

[ { "i":"0", "x":0, "y":0, "w":1, "h":2, "isResizable":false, "isDraggable":false, "isStatic":false, "maxH":10000, "maxW":10000, "minH":10000, "minW":10000 }, { "i":"1", "x":0, "y":2, "w":1, "h":8, "isResizable":false, "isDraggable":false, "isStatic":false, "maxH":10000, "maxW":10000, "minH":10000, "minW":10000 }, { "i":"3", "x":0, "y":6, "w":1, "h":8, "isResizable":false, "isDraggable":false, "isStatic":false, "maxH":10000, "maxW":10000, "minH":10000, "minW":10000 }, { "i":"4", "x":1, "y":4, "w":1, "h":8, "isResizable":false, "isDraggable":false, "isStatic":false, "maxH":10000, "maxW":10000, "minH":10000, "minW":10000 } ]

Error: Uncaught (in promise) Maximum recursive updates exceeded. This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself. Possible sources include component template, render function, updated hook or watcher source function. Promise.then (async) nextTick @ vue.runtime.esm-bundler.js:1755 Z @ vue-ts-responsive-grid-layout.es.js:4818 N @ vue-ts-responsive-grid-layout.es.js:4823 (anonymous) @ vue-ts-responsive-grid-layout.es.js:3923 emit @ vue-ts-responsive-grid-layout.es.js:3922 J @ vue-ts-responsive-grid-layout.es.js:4872 (anonymous) @ vue-ts-responsive-grid-layout.es.js:4882 Promise.then (async) nextTick @ vue.runtime.esm-bundler.js:1755 (anonymous) @ vue-ts-responsive-grid-layout.es.js:4881 Promise.then (async) nextTick @ vue.runtime.esm-bundler.js:1755 (anonymous) @ vue-ts-responsive-grid-layout.es.js:4880 (anonymous) @ vue.runtime.esm-bundler.js:4921 callWithErrorHandling @ vue.runtime.esm-bundler.js:1671 callWithAsyncErrorHandling @ vue.runtime.esm-bundler.js:1679 hook.weh.hook.weh @ vue.runtime.esm-bundler.js:4901 flushPostFlushCbs @ vue.runtime.esm-bundler.js:1847 flushJobs @ vue.runtime.esm-bundler.js:1885 Promise.then (async) queueFlush @ vue.runtime.esm-bundler.js:1788 queueJob @ vue.runtime.esm-bundler.js:1782 (anonymous) @ vue.runtime.esm-bundler.js:9284 resetScheduling @ vue.runtime.esm-bundler.js:533 triggerEffects @ vue.runtime.esm-bundler.js:576 triggerRefValue @ vue.runtime.esm-bundler.js:1329 set value @ vue.runtime.esm-bundler.js:1374 (anonymous) @ App.vue:75 Promise.finally (async) (anonymous) @ App.vue:72 Promise.then (async) (anonymous) @ App.vue:39 (anonymous) @ vue.runtime.esm-bundler.js:4921 callWithErrorHandling @ vue.runtime.esm-bundler.js:1671 callWithAsyncErrorHandling @ vue.runtime.esm-bundler.js:1679 hook.weh.hook.weh @ vue.runtime.esm-bundler.js:4901 flushPostFlushCbs @ vue.runtime.esm-bundler.js:1847 render2 @ vue.runtime.esm-bundler.js:9833 mount @ vue.runtime.esm-bundler.js:7005 app.mount @ vue.runtime.esm-bundler.js:12958 initAndRenderFrontend @ main.ts:100 Promise.then (async) (anonymous) @ main.ts:106

vincent-nagy commented 9 months ago

I have replaced my testdata with the testdata from the sandbox and the error is still happening.

gwinnem commented 9 months ago

I'll investigate it further tomorrow

vincent-nagy commented 9 months ago

Hi @gwinnem

I tried to reduce my code to as little as possible using the testdata from the sandbox and I still get the same errors. Below is the component that barely does anything at all now, I hope this can help identify the problem.

<template>
  <div class="overview-container">
      <div class="container-fluid includes-grid">

        <grid-layout
          v-model:layout="layout"
        >
          <grid-item
            v-for="item in layout"
            :x="item.x"
            :y="item.y"
            :w="item.w"
            :h="item.collapsed ? 2 : item.h"
            :i="item.i"
            :key="item.i"
          >
            <p>Component</p>
          </grid-item>
        </grid-layout>
      </div>
    </div>
</template>

<script setup>
import { ref} from 'vue';
import {GridLayout, GridItem} from "vue-ts-responsive-grid-layout";

const testData = [
  {
    i: 1,
    h: 2,
    w: 1,
    x: 0,
    y: 0,
    isDraggable: false,
    isResizable: false,
  },
  {
    i: 2,
    h: 1,
    w: 2,
    x: 1,
    y: 0
  },
  {
    i: 3,
    h: 2,
    w: 1,
    x: 2,
    y: 1
  },
  {
    i: 4,
    h: 2,
    w: 1,
    x: 3,
    y: 1,
    isStatic: true
  },
  {
    i: 5,
    h: 2,
    w: 1,
    x: 4,
    y: 0
  },
  {
    i: 6,
    h: 1,
    w: 1,
    x: 5,
    y: 0,
    isStatic: true
  },
  {
    i: 7,
    h: 3,
    w: 1,
    x: 0,
    y: 2,
    isDraggable: false,
    isResizable: false,
  },
  {
    i: 8,
    h: 1,
    w: 1,
    x: 1,
    y: 1,
    isStatic: true
  },];

const layout = ref([...testData]);

</script>

<style scoped lang="scss">

</style>
T0miii commented 9 months ago

This might be solved with the 1.2.8. As it comes with a fix to returning the proper cached layouts, and ignore those when resizing.

gwinnem commented 9 months ago

I have to test that release before I push it to npm. I'll try to get this done today. For now I will close this issue, if needed we can just reopen it later.

vincent-nagy commented 9 months ago

Hi @gwinnem

I just tried the new version (1.2.8) but the issue persists.

vincent-nagy commented 9 months ago

@gwinnem I've found that this is related to vue compat, without vue compat this issue doesn't occur.

gwinnem commented 9 months ago

@vincent-nagy Good to hear that.

Tnxs Vincent