4
votes

Please help me understand how to pass an imported single file vue component inside a vue-grid-layout item.

I know how to pass simple html, like here: https://jsfiddle.net/gmsa/jw2mmmpq/1/ But I need to insert other components with buttons and axios calls, etc

HTML:

<template>
  <div class="hello">
    <grid-layout
            :layout="layout"
            :col-num="12"
            :row-height="30"
            :is-draggable="true"
            :is-resizable="true"
            :vertical-compact="true"
            :margin="[10, 10]"
            :use-css-transforms="true"
    >

      <grid-item v-for="item in layout"
                 :x="item.x"
                 :y="item.y"
                 :w="item.w"
                 :h="item.h"
                 :i="item.i">
        <div v-html="item.c">
        </div>
        <Test></Test>
      </grid-item>
    </grid-layout>
  </div>
</template>

JS:

import VueGridLayout from 'vue-grid-layout';
  import Test from './test.vue';
  import Test from './test2.vue';

  let a = `This needs to be another component, like Test`;
  let b = `This needs to be another component, like Test2`;

  var testLayout = [
    {"x":0,"y":0,"w":2,"h":2,"i":"0", "c": a},
    {"x":2,"y":0,"w":2,"h":4,"i":"1", "c": b}
  ];
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  components: {
    GridLayout: VueGridLayout.GridLayout,
    GridItem: VueGridLayout.GridItem,
    Test,
    Test2
  },
  data: function (){
    return {
      layout: testLayout
    }
  }
}

Cannot find any ideas here:

https://github.com/jbaysolutions/vue-grid-layout

1

1 Answers

4
votes

You want dynamic components, which can be done using the <component :is="component"></component> syntax. If all of the items you wish to display are components, you could do something like this:

<grid-item v-for="item in layout"
             :x="item.x"
             :y="item.y"
             :w="item.w"
             :h="item.h"
             :i="item.i">
  <component :is="item.c"></component>
</grid-item>

And the JavaScript:

import VueGridLayout from 'vue-grid-layout';
import Test from './test.vue';
import Test2 from './test2.vue';
export default {
  components: {
    GridLayout: VueGridLayout.GridLayout,
    GridItem: VueGridLayout.GridItem,
    Test,
    Test2
  },
  data: function (){
    return {
      layout: [
        {"x":0,"y":0,"w":2,"h":2,"i":"0", "c": 'Test'}, // component name used but you could also use a reference to the component
        {"x":2,"y":0,"w":2,"h":4,"i":"1", "c": 'Test2'}
      ];
    }
  }
}

If only some of the items will be components and some are plain HTML, you could perhaps flag which are components in the layout array:

layout: [
        {"x":0,"y":0,"w":2,"h":2,"i":"0", "c": 'Test', isComponent: true},
        {"x":2,"y":0,"w":2,"h":4,"i":"1", "c": '<h1>Hello World</h1>', isComponent: false}
      ];

And then conditionally render the component or plain HTML in the grid-item slot.

<grid-item v-for="item in layout"
             :x="item.x"
             :y="item.y"
             :w="item.w"
             :h="item.h"
             :i="item.i">
  <template>
    <component v-if="item.isComponent" :is="item.c"></component>
    <div v-else v-html="item.c"></div>
  </template>
</grid-item>