[Vuejs]-Dynamic template with dynamic scope compilation

0👍

Would this work for you? Instead of using a component, you create a new element to be passed to bindPopup, and you new Vue on that element, with your data set appropriately.

new Vue({
  el: 'body',
  data: {
    popups: [1, 2, 3],
    message: "I'm Dad",
    statements: []
  },
  methods: {
    handleFeature: function(id) {
      const newDiv = document.createElement('div');
      const theStatement = {
        name: 'Some name for ' + id
        };
      newDiv.innerHTML = document.getElementById('map-statement-popup-template').innerHTML;
      new Vue({
        el: newDiv,
        data: {
          statement: theStatement
        },
        parent: this
      });

      // Mock call to layer.bindPopup
      const layerEl = document.getElementById(id);
      this.bindPopup(layerEl, newDiv);
    },
    bindPopup: function(layerEl, el) {
      layerEl.appendChild(el);
    }
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<div class="leaflet-zone">
  <div v-for="popup in [1,2,3]">
    <button @click="handleFeature('p-' + popup)">Bind</button>
    <div id="p-{{popup}}"></div>
  </div>
</div>

<template id="map-statement-popup-template">
  {{ statement.name }} {{$parent.message}}
</template>

I think you could do the same thing with $compile, but $compile is poorly (really un-) documented and intended for internal use. It is useful for bringing a new DOM element under control of the current Vue in the current scope, but you had a new scope as well as a new DOM element, and as you noted, that binding is exactly what Vue is intended to do.

You can establish a parent chain by specifying the parent option as I have updated my snippet to do.

👤Roy J

Leave a comment