How can add bootstrap tooltip inside Vue.js

2020-02-20 06:55发布

I have a page for listing data from table using Vue.js and Laravel. Listing data is successful. Delete and edit function is going on. For that purpose I have added two <span> (glyphicon-pencil), <span> (glyphicon-trash). If both <span> are outside the <template>tooltip shows, otherwise it doesn't works. Do you know how bootstrap tooltip works inside Vue Js. Thanks.

page.blade.php

    <template id="tasks-template">
       <table class="table table-responsive table-bordered table-hover">
            <thead>
                   <tr>
                   <th>#</th>
                   <th>Id</th>
                   <th>Religion</th>
                   <th>Action</th>
                   <th>Created</th>
                   <td>Status</td>
               </tr>
           </thead>

      <tbody>
             <tr v-for="(index, task) in list">
             <td><input type="checkbox" id="checkbox" aria-label="checkbox" value="checkbox"></td>
             <td>@{{ index + 1 }}</td>
            <td>@{{ task.religion | capitalize }}</td>
           <td v-if="task.status == 'publish'">
                     <span class="glyphicon glyphicon-ok"></span>
           </td>
           <td v-else>
                     <span class="glyphicon glyphicon-remove"></span>
           </td>
           <td>@{{ task.created_at }}</td>
           <td>
               <span class="glyphicon glyphicon-pencil" aria-hidden="true" data-toggle="tooltip" data-placement="left" title="Edit"></span> 
               <span class="glyphicon glyphicon-trash" aria-hidden="true" data-toggle="tooltip" data-placement="right" title="Delete"></span>
           </td>
         </tr>
       </tbody>
        </table>
        </template>

        <tasks></tasks> 
@push('scripts')
    <script src="/js/script.js"></script>
@endpush 

scripts.js

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


Vue.component('tasks', {

    template: '#tasks-template',

    data: function(){
        return{
            list: []
        };
    },

    created: function(){
        this.fetchTaskList();
    },

    methods: {
        fetchTaskList: function(){
            this.$http.get('/backend/religion/data', function(tasks){
                this.$set('list', tasks);
            });
        }
    }

});

new Vue({
   el: 'body'
});

9条回答
迷人小祖宗
2楼-- · 2020-02-20 07:37

Bootstrap Vue supports tooltips directly via the following syntax documented here.

<b-tooltip content="Tooltip Text">
    <b-btn variant="outline-success">Live chat</b-btn>
</b-tooltip>

Installation of Bootstrap Vue is quick and painless. See the quick setup guide for more details.

查看更多
我欲成王,谁敢阻挡
3楼-- · 2020-02-20 07:39

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

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

https://gist.github.com/victornpb/020d393f2f5b866437d13d49a4695b47

/**
 * Enable Bootstrap tooltips using Vue directive
 * @author Vitim.us
 * @see https://gist.github.com/victornpb/020d393f2f5b866437d13d49a4695b47
 * @example
 *   <button v-tooltip="foo">Hover me</button>
 *   <button v-tooltip.click="bar">Click me</button>
 *   <button v-tooltip.html="baz">Html</button>
 *   <button v-tooltip:top="foo">Top</button>
 *   <button v-tooltip:left="foo">Left</button>
 *   <button v-tooltip:right="foo">Right</button>
 *   <button v-tooltip:bottom="foo">Bottom</button>
 *   <button v-tooltip:auto="foo">Auto</button>
 *   <button v-tooltip:auto.html="clock" @click="clock = Date.now()">Updating</button>
 *   <button v-tooltip:auto.html.live="clock" @click="clock = Date.now()">Updating Live</button>
 */
Vue.directive('tooltip', {
  bind: function bsTooltipCreate(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).tooltip({
      title: binding.value,
      placement: binding.arg,
      trigger: trigger,
      html: binding.modifiers.html
    });
  },
  update: function bsTooltipUpdate(el, binding) {
    const $el = $(el);
    $el.attr('title', binding.value).tooltip('fixTitle');

    const data = $el.data('bs.tooltip');
    if (binding.modifiers.live) { // update live without flickering (but it doesn't reposition)
      if (data.$tip) {
        if (data.options.html) data.$tip.find('.tooltip-inner').html(binding.value);
        else data.$tip.find('.tooltip-inner').text(binding.value);
      }
    } else {
      if (data.inState.hover || data.inState.focus || data.inState.click) $el.tooltip('show');
    }
  },
  unbind(el, binding) {
    $(el).tooltip('destroy');
  },
});


//DEMO
new Vue({
  el: '#app',
  data: {
    foo: "Hi",
    bar: "There",
    baz: "<b>Hi</b><br><i>There</i>",
    clock: '00:00',
  },
  mounted() {
    setInterval(() => this.clock = new Date().toLocaleTimeString(), 1000);
  }
});
<link href="https://unpkg.com/bootstrap@3.3.7/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/bootstrap@3.3.7/dist/js/bootstrap.js"></script>
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>


<div id="app">
  <h4>Bootstrap tooltip with Vue.js Directive</h4>
  <br>
  <button v-tooltip="foo">Hover me</button>
  <button v-tooltip.click="bar">Click me</button>
  <button v-tooltip.html="baz">Html</button>
  <br>
  <button v-tooltip:top="foo">Top</button>
  <button v-tooltip:left="foo">Left</button>
  <button v-tooltip:right="foo">Right</button>
  <button v-tooltip:bottom="foo">Bottom</button>
  <button v-tooltip:auto="foo">Auto</button>

  <button v-tooltip:auto.html="clock" @click="clock = 'Long text test <b>bold</b>'+Date.now()">Updating</button>

  <button v-tooltip:auto.html.live="clock" @click="clock = 'Long text test  <b>bold</b>'+Date.now()">Updating Live</button>
</div>

查看更多
Juvenile、少年°
4楼-- · 2020-02-20 07:41

You can use this directive:

Vue.directive('tooltip', function(el, binding){
    $(el).tooltip({
             title: binding.value,
             placement: binding.arg,
             trigger: 'hover'             
         })
})

For example:

<span class="label label-default" v-tooltip:bottom="'Your tooltip text'">

Or you can also bind the tooltip text to a computed variable:

<span class="label label-default" v-tooltip:bottom="tooltipText">

And in your component script:

computed: {
    tooltipText: function() {
       // put your logic here to change the tooltip text
       return 'This is a computed tooltip'
    }
}
查看更多
劳资没心,怎么记你
5楼-- · 2020-02-20 07:45

You will find all the CDNs here without requirement of any registration of directive. Libray was made by Guillaume Chau

body {
  font-family: sans-serif;
  margin: 42px;
}

.tooltip {
  display: block !important;
  z-index: 10000;
}

.tooltip .tooltip-inner {
  background: black;
  color: white;
  border-radius: 16px;
  padding: 5px 10px 4px;
}

.tooltip .tooltip-arrow {
  width: 0;
  height: 0;
  border-style: solid;
  position: absolute;
  margin: 5px;
  border-color: black;
}

.tooltip[x-placement^="top"] {
  margin-bottom: 5px;
}

.tooltip[x-placement^="top"] .tooltip-arrow {
  border-width: 5px 5px 0 5px;
  border-left-color: transparent !important;
  border-right-color: transparent !important;
  border-bottom-color: transparent !important;
  bottom: -5px;
  left: calc(50% - 5px);
  margin-top: 0;
  margin-bottom: 0;
}

.tooltip[x-placement^="bottom"] {
  margin-top: 5px;
}

.tooltip[x-placement^="bottom"] .tooltip-arrow {
  border-width: 0 5px 5px 5px;
  border-left-color: transparent !important;
  border-right-color: transparent !important;
  border-top-color: transparent !important;
  top: -5px;
  left: calc(50% - 5px);
  margin-top: 0;
  margin-bottom: 0;
}

.tooltip[x-placement^="right"] {
  margin-left: 5px;
}

.tooltip[x-placement^="right"] .tooltip-arrow {
  border-width: 5px 5px 5px 0;
  border-left-color: transparent !important;
  border-top-color: transparent !important;
  border-bottom-color: transparent !important;
  left: -5px;
  top: calc(50% - 5px);
  margin-left: 0;
  margin-right: 0;
}

.tooltip[x-placement^="left"] {
  margin-right: 5px;
}

.tooltip[x-placement^="left"] .tooltip-arrow {
  border-width: 5px 0 5px 5px;
  border-top-color: transparent !important;
  border-right-color: transparent !important;
  border-bottom-color: transparent !important;
  right: -5px;
  top: calc(50% - 5px);
  margin-left: 0;
  margin-right: 0;
}

.tooltip[aria-hidden='true'] {
  visibility: hidden;
  opacity: 0;
  transition: opacity .15s, visibility .15s;
}

.tooltip[aria-hidden='false'] {
  visibility: visible;
  opacity: 1;
  transition: opacity .15s;
}

<script src="https://unpkg.com/popper.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/v-tooltip@2.0.2"></script>

<div id="app">
  <p><input v-model="message" placeholder="Message" /></p>
  <p><span v-tooltip="message">{{ message }}</span></p>
</div>

new Vue({
  el: '#app',
   data: {
    message: 'Hello Vue.js!'
  }
})

If the tooltip does not show on your page, most probably it is conflicting with some other library or the order of placing the CDNs on the page is not proper. In case your tooltip is being cut off on Chrome (will work in FireFox) due to conflict with bootstrap library, add max-width:100% to tooltip-inner to the v-tooltip style

.tooltip .tooltip-inner {
  **max-width:100%;**
  background: black;
  color: white;
  border-radius: 16px;
  padding: 5px 10px 4px;
}
查看更多
爷的心禁止访问
6楼-- · 2020-02-20 07:46

You should use this syntax, put it on index.html or on your general js file

$(function () {
  $('body').tooltip({
      selector: '[data-toggle="tooltip"]'
  });
});
查看更多
啃猪蹄的小仙女
7楼-- · 2020-02-20 07:47

If using Typescript Vue class components, install the jquery types:

npm install --save @types/jquery

And declare the directive like this in your Vue file, outside your component:

Vue.directive('tooltip', function(el, binding) {
    ($(el) as any).tooltip({
           title: binding.value,
           placement: binding.arg,
           trigger: 'hover'             
    })
});

Then use the sample HTML/bindings from @Ikbel's answer.

查看更多
登录 后发表回答