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 :)
Related
I need to show the status of an object if it has a property or not. I add a property id to object and console.log shows it is true, But it is not updated in DOM element.
How can I see the status in DOM element?
var app = new Vue({
el: '#app',
data() {
return {
children: {}
}
},
methods: {
fillChildren() {
this.children['id'] = 'child1Id'
console.log(this.children.hasOwnProperty('id')) // This is true
}
}
})
<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">
<div #click="fillChildren">Fill children</div>
{{children.hasOwnProperty('id')}} <!-- I want to see true after click -->
</div>
From Reactivity in Depth:
Vue cannot detect property addition or deletion.
You can circumvent this limitation by using the vm.$set instance method:
var app = new Vue({
el: '#app',
data() {
return {
children: {}
}
},
methods: {
fillChildren() {
this.$set(this.children, 'id', 'child1Id')
console.log(this.children.hasOwnProperty('id')) // This is true
}
}
})
<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">
<div #click="fillChildren">Fill children</div>
{{children.hasOwnProperty('id')}} <!-- I want to see true after click -->
</div>
I'm using markdown vue which is a plugin for vue. It says it's supposed to have superscript and subscript functionality built in, however when I run the code for a subscript I get something that looks like this
y = x b + e
i i i
In order to have this functionality I'm trying to use this plugin but I'm having a hardtime figuring out how it's supposed to be registered globally with the MarkdownItVue plugin. I tried doing this...
import MarkdownItVue from 'markdown-it-vue'
import MarkdownItSub from 'markdown-it-sub'
MarkdownItVue.use(MarkdownItSub)
Vue.use(MarkdownItVue)
But this is working out...
I'm happy to change approaches too if there's a simpler fix for MarkdownItVue
Update
index.html
<!DOCTYPE html>
<head>
<title>Hello World</title>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/markdown-it-vue#1.1.6/dist/markdown-it-vue.umd.min.js"></script>
<div id="app">
<div>
{{ msg }}
</div>
<markdown-it-vue :content="msg" class="md-body"></markdown-it-vue>
</div>
<script src="app.js"></script>
</body>
app.js
new Vue ({
el: '#app',
data() {
return {
msg: "$y_i = x_i + \\epsilon_i$"
}
}
})
It seems to be working just fine by default. See the example.
Anyway it seems from the docs that if you need to install additional markdown-it plugins, it needs to be done on component instance
const vm = new Vue({
el: "#app",
data() {
return {
content: "H~2~0 - 29^th^"
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/markdown-it-vue#1.1.6/dist/markdown-it-vue.umd.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/markdown-it-vue#1.1.6/dist/markdown-it-vue.css">
<div id="app">
<markdown-it-vue :content="content">
</markdown-it-vue>
</div>
The LaTeX rendering requires the stylesheet from markdown-it-vue. Make sure you're including it as a <link>:
<link rel="stylesheet" href="https://unpkg.com/markdown-it-vue#1.1.6/dist/markdown-it-vue.css">
new Vue({
el: "#app",
data() {
return {
content: "$y_i = x_i + \\epsilon_i$"
}
}
})
<script src="https://unpkg.com/vue#2.6.12/dist/vue.min.js"></script>
<script src="https://unpkg.com/markdown-it-vue#1.1.6/dist/markdown-it-vue.umd.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/markdown-it-vue#1.1.6/dist/markdown-it-vue.css">
<div id="app">
<markdown-it-vue class="md-body" :content="content"></markdown-it-vue>
</div>
Or importing the file from markdown-it-vue/dist/markdown-it-vue.css:
demo
Using b-modal Bootstrap Vue component, I'am trying to invoke especific method when the user clicks on the 'X' button at the right corner of the modal window.
I've tried with #close, #closeHeader, #closeheader without success.
<b-modal ok-only #ok="methodOk" #close="methodClose">
<span>Window closed</span>
</b-modal>
The #close event is what you're after.
If it isn't working for you, i suggest you check your version of BootstrapVue, or potential errors in your console.
new Vue({
el: '#app',
methods: {
onClose() {
alert('Modal X button pressed');
}
}
})
<link href="https://unpkg.com/bootstrap#4.5.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue#2.21.2/dist/bootstrap-vue.css" rel="stylesheet" />
<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.js"></script>
<div id="app">
<b-btn v-b-modal.my-modal>Open Modal</b-btn>
<b-modal id="my-modal" #close="onClose">
Click the `X` top right to see an alert.
</b-modal>
</div>
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>
I have an issue with loading Leaflet map using Vue.js and Bulma tab components (via Buefy).
If map is placed inside tab then it does not load all tiles until browser window is resized.
If map is placed outside of Bulma tabs component then it loads without any issue.
Calling map.invalidateSize() seems to help, but to do it automatically when tab changes I have to call it using setTimeout and put very big delay, like 1sec - which is very ugly.
How to get this working without this invalidateSize workaround?
Example with the issue: https://codepen.io/alxxnder/pen/zyYxwd
Example without the issue: https://codepen.io/alxxnder/pen/LMYEjr
Code:
new Vue({
el: '#app',
data: {
map: null,
},
methods: {
invalidateSize: function() {
this.map.invalidateSize();
}
},
mounted() {
this.map = L.map('map').setView([38.63, -90.23], 12);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(this.map);
}
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Leaflet Test</title>
<link rel="stylesheet" href="https://unpkg.com/buefy#0.7/dist/buefy.min.css">
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.4/dist/leaflet.css">
</head>
<body>
<div class="section">
<div class="container" id="app">
<b-tabs position="is-centered">
<b-tab-item label="Tab 1">
<div class="section">
Tab 1
<div class="map" id="map" style="height: 400px; width: 100%"></div>
<button class="button is-info" #click="invalidateSize()">invalidateSize</button>
</div>
</b-tab-item>
<b-tab-item label="Tab 2">
<div class="section">
Tab 2
</div>
</b-tab-item>
</b-tabs>
</div>
</div>
</body>
<script src="https://unpkg.com/vue#2"></script>
<script src="https://unpkg.com/buefy#0.7/dist/buefy.min.js"></script>
<script src="https://unpkg.com/leaflet#1.3.4/dist/leaflet.js"></script>
</html>
As explained in Data-toggle tab does not download Leaflet map, the issue is caused by the fact that your map container does not have yet its full size when you initialize it. You may understand it more easily if your map had been in an initially hidden tab (e.g. in tab 2).
As for your initially active tab (i.e. tab 1), it is probable that Buefy / Bulma still takes some time to reveal the tab content.
Since there is no event when the tab transition completes, you have to wait for the transition duration before calling the invalidateSize method. In your case, 300ms seems to be fine.
Then you should also call it again when the user changes the tab (see Buefy tabs events), otherwise should the browser had changed size while your tab was hidden, the same issue would happen again.
Demo with maps in the 2 tabs:
new Vue({
el: '#app',
data: {
map: null,
map2: null,
tabMaps: []
},
methods: {
invalidateSize: function(tabIndex) {
setTimeout(() => {
if (typeof tabIndex === "number") {
this.tabMaps[tabIndex].invalidateSize();
} else {
// invalidate all maps
this.tabMaps.forEach(map => {
map.invalidateSize();
});
}
}, 300);
}
},
mounted() {
this.map = L.map('map').setView([38.63, -90.23], 12);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(this.map);
// map2 in tab2
this.map2 = L.map(this.$refs.map2).setView([38.63, -90.23], 12);
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png").addTo(
this.map2
);
this.tabMaps.push(this.map); // 0
this.tabMaps.push(this.map2); // 1
this.invalidateSize();
}
})
<link rel="stylesheet" href="https://unpkg.com/buefy#0.7/dist/buefy.min.css">
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.4/dist/leaflet.css">
<div class="section">
<div class="container" id="app">
<b-tabs #change="invalidateSize" position="is-centered">
<b-tab-item label="Tab 1">
<div class="section">
Tab 1
<div class="map" id="map" style="height: 400px; width: 100%"></div>
<button class="button is-info" #click="invalidateSize()">invalidateSize</button>
</div>
</b-tab-item>
<b-tab-item label="Tab 2">
<div class="section">
Tab 2
<div class="map" ref="map2" style="height: 400px; width: 100%"></div>
</div>
</b-tab-item>
</b-tabs>
</div>
</div>
<script src="https://unpkg.com/vue#2"></script>
<script src="https://unpkg.com/buefy#0.7/dist/buefy.min.js"></script>
<script src="https://unpkg.com/leaflet#1.3.4/dist/leaflet.js"></script>