How can a Bootstrap-vue tooltip text be changed conditionally? - vue.js

How can a Bootstrap-vue tooltip text be changed conditionally by a checkbox? How can the tooltip text be accessed to change it? Any help would be greatly appreciated.
Vue component where a checkbox is attempting to change a tooltip:
<template>
<div class="text-center">
<b-button v-b-tooltip.hover.right="tooltipText" variant="outline-primary">
<div v-bind:class="{ active: checkbox1 }">
{{ username }}
</div>
</b-button>
</div>
</template>
<script>
export default {
props: ['username', 'checkbox1'],
data() {
return {
show: true,
tooltipTextContent: 'hello tooltip',
}
},
methods: {
tooltipText() {
if (!this.checkbox1) {
return this.tooltipTextContent
} else {
return `${this.tooltipTextContent} changed`
}
}
},
}
</script>
<style scoped>
.active {
color: red;
}
</style>

You just have to bind a value to the tooltip text that can be changed, like computed:
new Vue({
el: "#app",
data: {
username: 'Username1',
checkbox1: false,
tooltipTextContent: 'block'
},
computed: {
tooltipText() {
if (!this.checkbox1) {
return this.tooltipTextContent
} else {
return `${this.tooltipTextContent} changed`
}
}
}
})
.active {
color: red;
}
<!-- Load required Bootstrap and BootstrapVue CSS -->
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.css" />
<!-- Load polyfills to support older browsers -->
<script src="//polyfill.io/v3/polyfill.min.js?features=es2015%2CIntersectionObserver" crossorigin="anonymous"></script>
<!-- Load Vue followed by BootstrapVue -->
<script src="//unpkg.com/vue#latest/dist/vue.min.js"></script>
<script src="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.js"></script>
<!-- Load the following for BootstrapVueIcons support -->
<script src="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue-icons.min.js"></script>
<div id="app">
<div class="text-center">
<b-button v-b-tooltip.hover.right="tooltipText" variant="outline-primary">
<div v-bind:class="{ active: checkbox1 }">
{{ username }}
</div>
</b-button>
</div>
<b-form-checkbox id="checkbox-1" v-model="checkbox1" name="checkbox-1">
Change tooltip text?
</b-form-checkbox>
</div>

Related

How trigger click event after v-model's change on vue?

I have a checkBox on vuejs. I call a function when it's status changes, but click event triggers before the v-model changes. So the value of v-model in the function is the previous value. How Can I make the click event trigger after the v-model's change?
var app = new Vue({
el: '#app',
data() {
return {
status: false
}
},
methods: {
checkBoxClicked() {
console.log(this.status)
}
}
})
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap#4.5.3/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue#2.21.2/dist/bootstrap-vue.css" />
<script src="https://unpkg.com/vue#2.6.12/dist/vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.21.2/dist/bootstrap-vue.min.js"></script>
<div id="app">
<b-form-checkbox
v-model="status"
name="checkbox"
#click.native="checkBoxClicked"
>
I accept the terms and use
</b-form-checkbox>
</div>
Use change event instead of click:
<div id="app">
<b-form-checkbox
v-model="status"
name="checkbox"
#change="checkBoxClicked"
>
I accept the terms and use
</b-form-checkbox>
</div>
#atousadarabi
How about if you wait until the next render cycle, does that help?
methods: {
checkBoxClicked() {
this.$nextTick(() => {
console.log(this.status)
})
}
}
Otherwise just remove the click handler all together and have a watcher on status. Whenever it updates do what you need to :)

How can i close the vue popover when i scroll the screen

I haven't decided any popover for Vue.
Device is Touch devices
For touch devices I need click event for opening of popover.
Scenario:
I used Vue bootstrap popover or tooltip
it is stuck to the screen when I am scrolling.
I need to remove when scrolling
You can use this snippet:
new Vue({
el: "#app",
methods: {
do_sth() {
this.$root.$emit('bv::hide::popover')
}
},
created () {
window.addEventListener('scroll', this.do_sth);
},
});
body .wrapper {
padding: 100px 20px;
min-height: 2000px;
}
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap#4.5.3/dist/css/bootstrap.min.css" />
<script src="https://unpkg.com/vue#2.6.12/dist/vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.21.2/dist/bootstrap-vue.min.js"></script>
<div id="app">
<div class="wrapper">
<b-button
href="#"
tabindex="0"
v-b-popover.click="'Popover content'"
title="Popover title"
>
Link button with popover directive
</b-button>
</div>
</div>

How to appendChild a component in DOM with VueJS?

I followed this tutorial https://css-tricks.com/creating-vue-js-component-instances-programmatically/
My component :
const button = Vue.component('button', {
props: {
id: String,
color: String
},
data: function() {
return {
count: 0
}
},
template:
`
<div class="button">
{{ count }}
</div>
`
});
The html :
<html>
<head>
<title>Test</title>
</head>
<body>
<div id="app">
<main id="main" ref="container">
<span #click="add">Add</span>
</main>
</div>
</body>
<script src="vue.js"></script>
<script src="app.js"></script>
</html>
All is fine but at this step I get the error "instance is not a html node" How to make vue component as a html node ?
ComponentClass = Vue.extend(button)
instance = new ComponentClass()
this.$refs.container.appendChild(instance.$el)

bootstrap-vue multi level drop down

i'm using bootstrap-vue and i have a multi level drop down menu (for categories) . this is official site example :
https://bootstrap-vue.org/docs/components/dropdown
<b-dropdown id="dropdown-1" text="Dropdown Button" class="m-md-2">
<b-dropdown-item>First Action</b-dropdown-item>
<b-dropdown-item>Second Action</b-dropdown-item>
</b-dropdown>
but i don't know how to create a multi level menu (i copy drop downs inside each other but it does not work) ! it has only 1 level drop down example ! how can i create a multi level one ?
tnx
So as I mentioned in my comments you can wrap b-dropdown events and do something custom like this:
window.onload = () => {
new Vue({
el: '#app',
data() {
return {
name: 'BootstrapVue',
isDropdown2Visible: false
}
},
mounted: function () {
this.$root.$on('bv::dropdown::show', bvEvent => {
if(bvEvent.componentId === 'dropdown-2') {
this.isDropdown2Visible = true;
}
})
this.$root.$on('bv::dropdown::hide', bvEvent => {
if(bvEvent.componentId === 'dropdown-2') {
this.isDropdown2Visible = false;
}
if(this.isDropdown2Visible) {
bvEvent.preventDefault()
}
})
}
})
}
body { padding: 1rem; }
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap#4.5.3/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue#2.21.2/dist/bootstrap-vue.css" />
<script src="https://unpkg.com/vue#2.6.12/dist/vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.21.2/dist/bootstrap-vue.min.js"></script>
<div id="app">
<b-dropdown id="dropdown-1" text="Dropdown Button 1" class="m-md-2">
<b-dropdown-item>First Action 1</b-dropdown-item>
<b-dropdown-item>Second Action 1</b-dropdown-item>
<b-dropdown id="dropdown-2" text="Dropdown Button 2" class="m-md-2">
<b-dropdown-item>First Action 2</b-dropdown-item>
<b-dropdown-item>Second Action 2</b-dropdown-item>
</b-dropdown>
</b-dropdown>
</div>
You can try something like this
This snippet contains logic for one level menu.You can edit code as
per your requirement
JSBin Link
new Vue({
el: "#app",
data: {
menu: [
{ title : 'one'},
{ title : 'two'},
{ title : 'three',showSubMenu : false,
children : [
{ title : 'four'},
{ title : 'five'},
]},
]
},
methods : {
toogleItem(index){
if(this.menu[index].children){
if(!this.menu[index].showSubMenu){
this.menu[index].showSubMenu = true
} else {
this.menu[index].showSubMenu = false
}
}
}
}
})
.sub-menu{
position: absolute;
min-width: 10rem;
padding: .5rem 0;
margin: .125rem 0 0;
font-size: 1rem;
color: #212529;
text-align: left;
list-style: none;
background-color: #fff;
background-clip: padding-box;
border: 1px solid rgba(0,0,0,.15);
border-radius: .25rem;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<!-- Load required Bootstrap and BootstrapVue CSS -->
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.css" />
<!-- Load polyfills to support older browsers -->
<script src="//polyfill.io/v3/polyfill.min.js?features=es2015%2CIntersectionObserver" crossorigin="anonymous"></script>
<!-- Load Vue followed by BootstrapVue -->
<script src="//unpkg.com/vue#latest/dist/vue.min.js"></script>
<script src="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.js"></script>
<!-- Load the following for BootstrapVueIcons support -->
<script src="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue-icons.min.js"></script>
</head>
<body>
<div id="app">
<b-dropdown id="dropdown-1" text="Dropdown Button" class="m-md-2">
<b-dropdown-item
v-for="(item,index) in menu"
:key="index"
#mouseover.native="toogleItem(index)"
#mouseout.native="toogleItem(index)">
<span>{{item.title}} <b-icon-caret-down-fill :scale="0.6" v-if="item.children"></b-icon-caret-down-fill></span>
<div v-if="item.children" class="sub-menu" v-show="item.showSubMenu">
<b-dropdown-item v-for="(item,index) in item.children" :key="index">{{item.title}}
</b-dropdown-item>
</div>
</b-dropdown-item>
</b-dropdown>
</div>
</body>
</html>

Polymer2.0 - is it possible to set default value in dom-repeat?

I am trying to set the default value in dom-repeat.
In below example, I am trying to display default image(http://img04.deviantart.net/8465/i/2009/260/f/a/blender__texture_dummy_by_3d_asuarus.jpg) in dom repeat if the image is not available or undefined
I think , we cant use doublepipe operator in the expression [[item.image]]
HTML:
<head>
<base href="https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/">
<link rel="import" href="polymer/polymer.html">
</head>
<body>
<x-custom></x-custom>
<dom-module id="x-custom">
<template>
<style>
.test{
display:inline;
float:left;
border:1px solid black;
margin:5px;
padding:5px;
text-align:center;
}
</style>
<div> Employee list: </div>
<template is="dom-repeat" items="{{employees}}">
<div class="test">
<div># [[index]]</div>
<div>First name: <span>[[item.first]]</span></div>
<div>Last name: <span>[[item.last]]</span></div>
<div><img src="[[item.image]]" width="50px"></div>
</div>
</template>
</template>
</dom-module>
JS:
class XCustom extends Polymer.Element {
static get is() { return 'x-custom'; }
static get properties() {
return {
employees: {
type: Array,
value() {
return [
{first: 'Bob', last: 'Smith',image:'https://dummyimage.com/300.png/09f/fff'},
{first: 'Adam', last: 'Gilchrist',image:'https://cdn.pixabay.com/photo/2015/03/04/22/35/head-659652_960_720.png'},
{first: 'Sally', last: 'Johnson'},
];
}
}
}
}
}
customElements.define(XCustom.is, XCustom);
Codepen- https://codepen.io/nagasai/pen/EvPdLB
No, we cannot use pipe operator. But:
If you are just after setting a default value for image if not found or null:
<object data="[[item.image]]" type="image/png" width="50px">
<img src="http://img04.deviantart.net/8465/i/2009/260/f/a/blender__texture_dummy_by_3d_asuarus.jpg" width="50px"/>
</object>
More at: Inputting a default image in case the src attribute of an html <img> is not valid?
For other items you can use <dom-if>:
<span>
<template is="dom-if" if="[[!item.first]]">DefaultValue
</template>
[[item.first]]
</span>
I hope this helps.