Vue2leaflet: Sub-component inside v-popup and v-tooltip

Created on 10 May 2017  路  9Comments  路  Source: vue-leaflet/Vue2Leaflet

Hi @KoRiGaN,

Is it possible to use sub-component inside the content of v-popup and v-tooltip, instead of pure HTML string inside the content property?

So we can do this kind of stuff:

<div id="app">
  <v-map :zoom="zoom" :center="center">
    <v-tilelayer :url="url" :attribution="attribution"></v-tilelayer>
    <v-marker :lat-lng="marker">
      <v-popup>
        <button @click='counter += 1'>{{ some_content }}</button>
      </v-popup>
    </v-marker>
  </v-map>
</div>

Cheers,
Tortue Torche

help wanted

Most helpful comment

@tortuetorche I was trying to do the same thing but couldn't quite figure it out. I ended up creating a new component with properties. As you need to build up a string to pass to bindPopup. It might not be the best method but it did work.

<template>
</template>

<script>

    import eventsBinder from '../utils/eventsBinder.js';
    import propsBinder from '../utils/propsBinder.js';

    const events = [
        'add',
        'remove',
        'popupopen',
        'popupclose',
        'tooltipopen',
        'tooltipclose'
    ];

    const props = {
        content: {
            default: '',
        },
        thumbnail: {
            default: '',
        },
        rating: {
            default: 0,
        },
        link: {
            default: ''
        }
    };

    export default {
        props: props,
        computed: {
            // a computed getter
            popupContent: function () {
                // There is probably a better way to do this
                return `
                    <div class="media">
                      <div class="media-left">
                        <img src="${this.thumbnail}" alt="" height="72" width="72">
                      </div>
                      <div class="media-body">
                        <a href="${this.link}"><h6 class="media-heading">${this.content}</h6></a>
                        Rating: <b>${this.rating}</b>
                      </div>
                    </div>
                `;
            }
        },
        mounted() {
            this.mapObject = L.popup();
            eventsBinder(this, this.mapObject, events);
            propsBinder(this, this.mapObject, props);
            if (this.$parent._isMounted) {
                this.deferredMountedTo(this.$parent.mapObject);
            }
        },
        beforeDestroy() {
            if (this.parent.getPopup()) {
                this.parent.unbindPopup();
            }
        },
        methods: {
            deferredMountedTo(parent) {
                this.parent = parent;
                parent.bindPopup(this.popupContent);
            },
            setContent(newVal, oldVal) {
                if (newVal) {
                    this.parent.bindPopup(this.popupContent);
                } else {
                    if (this.parent.getPopup()) {
                        this.parent.unbindPopup();
                    }
                }
            },
        }
    };
</script>

All 9 comments

@tortuetorche I was trying to do the same thing but couldn't quite figure it out. I ended up creating a new component with properties. As you need to build up a string to pass to bindPopup. It might not be the best method but it did work.

<template>
</template>

<script>

    import eventsBinder from '../utils/eventsBinder.js';
    import propsBinder from '../utils/propsBinder.js';

    const events = [
        'add',
        'remove',
        'popupopen',
        'popupclose',
        'tooltipopen',
        'tooltipclose'
    ];

    const props = {
        content: {
            default: '',
        },
        thumbnail: {
            default: '',
        },
        rating: {
            default: 0,
        },
        link: {
            default: ''
        }
    };

    export default {
        props: props,
        computed: {
            // a computed getter
            popupContent: function () {
                // There is probably a better way to do this
                return `
                    <div class="media">
                      <div class="media-left">
                        <img src="${this.thumbnail}" alt="" height="72" width="72">
                      </div>
                      <div class="media-body">
                        <a href="${this.link}"><h6 class="media-heading">${this.content}</h6></a>
                        Rating: <b>${this.rating}</b>
                      </div>
                    </div>
                `;
            }
        },
        mounted() {
            this.mapObject = L.popup();
            eventsBinder(this, this.mapObject, events);
            propsBinder(this, this.mapObject, props);
            if (this.$parent._isMounted) {
                this.deferredMountedTo(this.$parent.mapObject);
            }
        },
        beforeDestroy() {
            if (this.parent.getPopup()) {
                this.parent.unbindPopup();
            }
        },
        methods: {
            deferredMountedTo(parent) {
                this.parent = parent;
                parent.bindPopup(this.popupContent);
            },
            setContent(newVal, oldVal) {
                if (newVal) {
                    this.parent.bindPopup(this.popupContent);
                } else {
                    if (this.parent.getPopup()) {
                        this.parent.unbindPopup();
                    }
                }
            },
        }
    };
</script>

Hi @tortuetorche,

Not sure how to implement that properly with Vue.
If someone can give a little help on that it would be welcome. :-)

Hi,

I think that it could work using in the v-popup template https://vuejs.org/v2/guide/components.html#Single-Slot

Then, using the method popup.setContent( htmlContent), the content can be all the slot content.

I don't get it, how am I supposed to use
a <router-link> for example inside a popup?
I just viewed the examples, but none of them
were using vue-components inside a pop-up.

For me, :content="[...]" renders sub-components as inactive html only.

Hi @fdenzer,
Give a look at MarkerPopupExample and MarkerPopup in the example folder provided in the repo.
Let me know if it helps.

Micka

Hi @KoRiGaN ,
we took a look at the example,
yet we did not get router-link to
render as a sub-component in our
custom component like this:

<template>
  <div>
    <h2>Popup</h2>
    <div><router-link :to="'/'">back home</router-link></div>

  </div>
</template>

Me also need to work router-link inside popup. @fdenzer do you find the solution?
If anyone has found the solution and can share, I will be grateful.
Thanks.

@core01 my case was probably just caused by inexperience with the prop syntax:
<div><router-link to=" '/' "> without a colon looks plain wrong.

Note that, in order to not reference a property called /,
the syntax needs to contain two more single quotation marks.
Becauseto="{/}" would behave like :to="/", which makes no sense.

Could you have misspelled something, too?

Nice feature.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

shtw picture shtw  路  5Comments

srtonz picture srtonz  路  4Comments

hoticer picture hoticer  路  3Comments

mpallante picture mpallante  路  4Comments

lufias picture lufias  路  3Comments