Vuejs: Callback after render
Asked Answered
N

3

10

I have a Bootstrap popover that I want to attach to an element that has a conditional render; therefore, I must trigger $().popover() after the element has been attached to the DOM.

Is there a way to trigger a callback after a v-if statement inserts the elements into the DOM?

Nashville answered 14/2, 2017 at 21:45 Comment(0)
G
17

Use this in vuejs 2:

updated: function() {
    $('[data-toggle="tooltip"]').tooltip();
},

take a look here

Gaussmeter answered 30/5, 2017 at 10:23 Comment(0)
E
5

The right way to do this, is making it a directive, so you can hook into the life cycle of a DOM element.

Using nextTick is not the right way to do it for a few reasons, it can break if the DOM reacts and re render a part of your view. You are not destroying tooltips after initialisation. This can break because nextTick is async, and something in between render and nextTick can change your DOM state.

https://v2.vuejs.org/v2/guide/custom-directive.html

/* Enable Bootstrap popover using Vue directive */
Vue.directive('popover', {
    bind: bsPopover,
    update: bsPopover,
    unbind (el, binding) {
        $(el).popover('destroy');
    }
});
function bsPopover(el, binding) { 
    let trigger;
    if (binding.modifiers.focus || binding.modifiers.hover || binding.modifiers.click) {
        const t = [];
        if (binding.modifiers.focus) t.push('focus');
        if (binding.modifiers.hover) t.push('hover');
        if (binding.modifiers.click) t.push('click');
        trigger = t.join(' ');
    }
    
    $(el).popover('destroy'); //update
    $(el).popover({
        title: typeof binding.value==='object'? binding.value.title : undefined,
        content: typeof binding.value==='object'? binding.value.content : binding.value,
        placement: binding.arg,
        trigger: trigger,
        html: binding.modifiers.html
    });
}


//DEMO
new Vue({
  el: '#app',
  data: {
    foo: "Hover me",
    bar: "There",
    baz: {content: "<b>Hi</b><br><i>There</i>", title: "Test"},
  }
});
<link href="https://unpkg.com/[email protected]/dist/css/bootstrap.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/js/bootstrap.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>


<div id="app">
  <h4>Bootstrap popover with Vue.js Directive</h4>
  <br>
  <input v-model="foo" v-popover.hover="foo"/>
  <button v-popover.click="bar">Click me</button>
  <button v-popover.html="baz">Html</button>
  <br>
  <button v-popover:top="foo">Top</button>
  <button v-popover:left="foo">Left</button>
  <button v-popover:right="foo">Right</button>
  <button v-popover:bottom="foo">Bottom</button>
  <button v-popover:auto="foo">Auto</button>
</div>
Exercise answered 9/4, 2018 at 16:40 Comment(0)
T
3

Vue.nextTick() defers the execution of the callback to be executed after the next update of the DOM, see: VueJS API reference

Titoism answered 14/2, 2017 at 22:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.