3

I'm trying to make reusable components for gridstack.

I cannot find a simple way to do something similar to this.$compile method from vue 1. I've seen this example.

Here is my vue script:

export default {
  components: {
    'horizontal-fab': HorizontalFab,
    'd-widget': DWidget
  },
  data () {
    return {
  }
},
mounted () {
  var options = {
    cellHeight: 80,
    verticalMargin: 10,
    width: 3
  }
  $('#grid-stack').gridstack(options)
},

addWid () {
  var grid = $('#grid-stack').data('gridstack')
  grid.addWidget('<d-widget></d-widget>', 0, 0, 1, 1, true)
},

addGraph () {
  var grid = $('#grid-stack').data('gridstack')
  grid.addWidget(`
    <div class="grid-stack-item" data-gs-width="4">
      <div class="grid-stack-item-content">
        <p>HTML (added)</p>
      </div>
    </div>
  `, 0, 0, 1, 1, true)
}

And here is relevant html:

<span @click="addGraph" >Line graph</span></li>
<span @click="addWid">Sparklines</span></li>
...
<div id="grid-stack" class="grid-stack grid-stack-3">
  <d-widget data-gs-x="0" data-gs-y="0" data-gs-width="1" data-gs-height="1"></d-widget>
</div>

The problem is:

that method addGraph works perfectly, when addWid - does not. Even though when inserting as a component directly in the html, it works too.

I guess that it because html from the component is not being precompiled. It was solved by compile in vue1 though.

What I've already tried:

  1. Mount, as suggested here, but it wasn't working because it couldn't see defined components, I guess
  2. I've seen there are a possibilities to make it work with push , as suggested here. But my vue knowledge is not that strong yet, and I cannot find a way to make it work in this way, since there would be several types of blocks, and all of them should be treated by gridstack as the same elements. Plus, same component may be used several times within one board, with different parameters.
  3. I've seen there is a method to compile a standalone component, like here, but looks like it is highly unrecommended, so I'm looking for other ways.
  4. I've also seen these render functions, but again - unfortunately my skills are not that good to apply it.

So, to sum it up - I'd really appreciate some advice about these methods, or maybe recommendations on the other way of implementing this. Problem is that I should also count on gridstack script, and not simply inserting the elements.

Thanks!

UPD: definition of d-widget:

This is basically single component, which is defined in the separate file, called Widget.vue

<template>
<div class="grid-stack-item" data-gs-width="4">
    <div class="grid-stack-item-content">
        <p>Wiiidget! (added)</p>
    </div>
</div>
</template>
<script>
export default {
  data () {
    return {
    }
  }
}
</script>
tony19
  • 125,647
  • 18
  • 229
  • 307
Olenka
  • 259
  • 3
  • 12
  • What is a `d-widget`? Can we see the definition? – Bert Mar 27 '17 at 00:28
  • @BertEvans , thanks for your question! I've just added the definition, and you may see that it is basically the same template which I'm using in addGraph (), just imported as a component, and not html. – Olenka Mar 27 '17 at 08:10
  • Are you every going to add more than just HTML to the `d-widget` component or is it just going to be a template. Essentially your problem is by using a single file component, the template is compiled to a render function and you really just want the template itself (as it stands now). – Bert Mar 27 '17 at 15:53
  • @BertEvans yep, you understand it correctly. But yes, I'll need to have a way more in that component, I'll also send parameters and template itself would be more complicated (d3 graphs). This is just a basic example to understand a problem. So I cannot find a way to prerender (let's call it like that) the html from the component before serving it to the addWid () method – Olenka Mar 27 '17 at 16:43
  • @BertEvans I'm now also looking into vue property, maybe that's another way to do this – Olenka Mar 27 '17 at 16:48

2 Answers2

1

Using mount, you should be able to get what you need to pass to grid.addWidget.

First we want to turn the component into something we can construct.

const MyWidget = Vue.extend(DWidget);

Then, we can mount that constructor.

const mounted = new MyWidget().$mount();

My passing nothing to $mount(), it will not add the component to the DOM. We can get access to the element it generated using mounted.$el. I expect you should be able to pass that to addWidget.

grid.addWidget(mounted.$el, 0,0,1,1,true);
tony19
  • 125,647
  • 18
  • 229
  • 307
Bert
  • 80,741
  • 17
  • 199
  • 164
  • Hi, Bert. Well, in a way it helped! Thanks! Now when I call addWid () for the first time - it really is generated! And everything is in a good order. But, when I call this method once again - adds one more component, though removes previous one at all. (so gridstack just leaves blank space instead of the 1st one). Though I can add as many components as I need with addGraph () , and all of them are shown at the same time – Olenka Mar 27 '17 at 17:55
  • oh, I had just realized some my mistake, and now it works :) ! Great, thanks a lot! – Olenka Mar 27 '17 at 18:06
0

So, as @Bert suggested I had to use mount. And his method works perfectly. And here is a resulting addWid () method, which actually works as reusable component:

addWid () {
  const MyWidget = Vue.extend(DWidget)
  const mounted = new MyWidget().$mount()
  var grid = $('#grid-stack').data('gridstack')
  grid.addWidget(mounted.$el, 0, 0, 1, 1, true)
}

Hopefully it would be helpful to someone!

Olenka
  • 259
  • 3
  • 12