I'm trying to work with pagination using the v-pagination component from bootstrap-vue. It's working more or less as I want, however when I click on a certain page the component is closing.
I would like to know how I can prevent v-select from closing before I select one of the options.
My code:
<v-select
id="municipio"
v-model="municipioState"
:options="municipiosPaginaAtual"
:filterable="false"
placeholder="Selecione seu município"
label="municipio"
#search="buscarMunicipio"
>
<div slot="no-options">
Selecione o Estado!
</div>
<li
slot="list-footer"
class="pagination"
#click.prevent=""
>
<b-pagination
v-model="municipioPaginacao"
:total-rows="municipiosFiltradosQuantidade"
:per-page="limit"
first-number
last-number
/>
</li>
</v-select>
If there is a workaround or other option than v-select I would be pleased to know.
you can use #mouseup.native.capture.stop in the b-pagination tag to prevent closing the dropdown of the vue-select.
Also, in my opinion, you can use vue-multiselect for a better user experience, but it's up to you and your need. I just wanted to suggest it to you as another option.
I provided a simple snippet to show this:
Vue.component("v-select", VueSelect.VueSelect);
new Vue({
el: '#app',
data() {
return {
books: [{
title: "Old Man's War"
},
{
title: "The Lock Artist"
},
{
title: "HTML5"
},
{
title: "Right Ho Jeeves"
},
{
title: "The Code of the Wooster"
},
{
title: "Thank You Jeeves"
}
],
perPage: 2,
currentPage: 1,
rows: 6
}
},
})
<link href="https://unpkg.com/vue-select#3.16.0/dist/vue-select.css" rel="stylesheet"/>
<script src="https://unpkg.com/vue-select#3.16.0/dist/vue-select.js"></script>
<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">
<v-select :options="books" label="title">
<li slot="list-footer">
<b-pagination #mouseup.native.capture.stop v-model="currentPage" :total-rows="rows" :per-page="perPage"></b-pagination>
</li>
</v-select>
</div>
Related
I would like to ask if someone see the problem in my code.
Everything render ok, no problem with the render, the issue is that every time I click in one panel content all the panel-content of every group with the same index expand or collapse and not only the one that I clicked.
Any idea?? Thanks a lot.
<div v-for="(group, i) in groups" :key="i" class="pb-4">
<p class="text-h5 primary text-center white--text">{{ group.title }}</p>
<div v-if="group.links">
<a v-for="(link, u) in group.links" :key="u" :href="link.src" class="black--text"> {{ link.title }}</a>
</div>
<v-expansion-panels v-model="activesPanels" multiple accordion dense flat>
<v-expansion-panel v-for="(item, v) in group.fact" v-show="shouldRender(v)" :key="v">
<v-expansion-panel-header class="px-0">{{ item.title }}</v-expansion-panel-header>
<v-expansion-panel-content>
<type :fact="item" :models="models" />
</v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
</div>
The reason for this issue is that you are using the same v-model variable activesPanels for every group. The activesPanels should belong to each group to maintain their opening and closing state individually.
Also, use the unique properties for template keys to avoid errors i.e, "Duplicate keys detected".
Here is the working demo-
<!DOCTYPE html>
<html>
<head>
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#6.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
</head>
<body>
<div id="app">
<v-app id="inspire">
<div v-for="(group, i) in groups" :key="i">
<p class="primary text-center white--text">{{ group.title }}</p>
<div v-if="group.links">
<a v-for="link in group.links" :key="link.src" :href="link.src" class="black--text"> {{ link.title }}</a>
</div>
<v-expansion-panels v-model="group.activesPanels" multiple accordion dense flat>
<v-expansion-panel v-for="item in group.fact" :key="item.title">
<v-expansion-panel-header class="pa-0">{{ item.title }}</v-expansion-panel-header>
<v-expansion-panel-content class="pa-0">
Hello
</v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
</div>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<script>
new Vue({
el: '#app',
data () {
return {
groups: [
{
title: "group1",
activesPanels: [],
fact: [
{
title: 'fact1'
}
],
links:[
{
src: "https://google.com",
title: "Hello"
},
{
src: "https://twitter.com",
title: "Hello"
}
]
},
{
title: "group2",
activesPanels: [],
fact: [
{
title: 'fact2'
}
],
links:[
{
src: "https://www.shorturl.at/",
title: "Hello"
},
{
src: "https://www.npmjs.com/package/vuex-map-fields",
title: "Hello"
}
]
}
]
}
},
vuetify: new Vuetify(),
})
</script>
</body>
</html>
You should avoid using indexes as keys in your v-for loop. The keys need to be unique for every element. By using index you have probably 2 elements with index 0 as a key. Vue cannot keep track of changes in the DOM that way. It is getting even worse if you edit the array and items in the array get another index.
So, you can use a unique value for the key, maybe an id or link.url and item.title in your code.
See docs:
https://vuejs.org/guide/essentials/list.html#maintaining-state-with-key
I have a code where I can add inputs, with #click="addInput()" .
Now I'm trying do delete these inputs as well with #click="deleteInput(). I've tried to do this with this.inputs.splice(index, 1) - but when I try this only my last input will be deleted.. but I don't know why..
How can I solve that, that my specific Input which I want to delete will be deleted?
The additional code in my inputs at addInput -> name is from child element
Thanks for helping me out!
my template:
<template>
<div >
<div class="mt-2" v-for="(id, index) in inputs" :key="index">
<div class="row mb-3">
<b-button-group class="col-md-12">
<b-button class="col-md-8" v-b-toggle="toggleElementInChildVue" variant="danger"></b-button>
<b-button #click="deleteInput(index)" class="col-md-4" variant="danger">Delete this!</b-button>
</b-button-group>
</div>
</div>
<div>
<b-button #click="addInput()">Add Input</b-button>
</div>
</div>
</template>
my script:
<script>
export default {
name: 'test',
data() {
return {
inputs: [{
name: "",
}],
}
},
methods: {
deleteInput(index) {
this.inputs.splice(index, 1)
},
addInput() {
this.inputs.push({
name: "",
})
},
},
}
</script>
Looks like your delete method works, check snippet pls:
new Vue({
el: '#demo',
data() {
return {
inputs: [{
name: "aa",
}],
}
},
methods: {
deleteInput(index) {
this.inputs.splice(index, 1)
},
addInput() {
this.inputs.push({
name: "bb",
})
},
},
})
Vue.config.productionTip = false
Vue.config.devtools = false
<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="demo">
<div >
<div class="mt-2" v-for="(name, index) in inputs" :key="index">
<div class="row mb-3">
<b-button-group class="col-md-12">
<b-button class="col-md-8" variant="danger">{{name}}</b-button>
<b-button #click="deleteInput(index)" class="col-md-4" variant="danger">Delete this!</b-button>
</b-button-group>
</div>
</div>
<div>
<b-button #click="addInput()">Add Input</b-button>
</div>
</div>
</div>
The sample code below is taken from the JSFiddle on the vue-multiselect (v2) GitHub page and put into a single html page for the purposes of this example.
If you uncomment the v2 script/link tags and comment out the v3 tags. It works fine. However, using the v3 tags as shown gives the error "Uncaught TypeError: window.VueMultiselect is undefined".
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<multiselect
v-model="value"
:options="options"
:close-on-select="false"
:clear-on-select="false"
:hide-selected="true"
:preserve-search="true"
placeholder="Pick some"
label="name"
track-by="name"
:preselect-first="true"
id="example"
#select="onSelect"
>
</multiselect>
<pre class="language-json"><code>{{ value }}</code></pre>
</div>
<!-- WORKS: vue 2 + vue-multiselect 2
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.12/dist/vue.js"></script>
<script src="https://unpkg.com/vue-multiselect#2.1.6"></script>
<link rel="stylesheet" href="https://unpkg.com/vue-multiselect#2.1.6/dist/vue-multiselect.min.css">
-->
<!-- DOES NOT WORK: vue 3 + vue-multiselect 3 -->
<script src="https://unpkg.com/vue#next"></script>
<script src="https://unpkg.com/vue-multiselect#3.0.0-alpha.2"></script>
<link rel="stylesheet" href="https://unpkg.com/vue-multiselect#3.0.0-alpha.2/dist/vue-multiselect.css">
<script>
new Vue({
components: {
Multiselect: window.VueMultiselect.default
},
data: {
value: '',
options: [
{ name: 'Vue.js', language: 'JavaScript' },
{ name: 'Rails', language: 'Ruby' },
{ name: 'Sinatra', language: 'Ruby' },
{ name: 'Laravel', language: 'PHP', $isDisabled: true }
]
},
methods: {
customLabel (option) {
return `${option.library} - ${option.language}`
},
onSelect (option, id) {
console.log(option, id)
}
}
}).$mount('#app')
</script>
</body>
</html>
Ran into a case to trigger a click once a page or view is loaded, and a popup is triggered in vue.js to edit data table row. There is no such a good VUE way that I can find, although the following link mentioned a way as the follows:
https://forum.vuejs.org/t/how-to-trigger-a-click-event-through-code-in-vuejs-on-page-load/92582
mounted: function () {
setTimeout(function(){
const elem = document.getElementById('myBtn');
elem.click();
}, 100);
},
I did in a similar way as the follows. The try catch to contain error although it's ugly, since at some point the data doesn't exist.
edit: function (idx, row) {
... nore code here ...
try {
document.getElementById(row.id).click(); // row.id is dynamic or variable
} catch (error) {
// pass
}
},
However my team mate, a vue.js lover, said it's not a damn VUE way. Now what it the right way to do such a thing?
The following Demo is possible for the expected work:
Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue({
el: '#app',
data: {
li_address: [{name: 'CA'}, {name: 'NY'}, {name: 'AL'}],
name: 'NY'
},
methods: {
},
mounted() {
console.log(['this.name', this.name]);
// this.$refs[this.name].click(); // failed
document.getElementById(this.name).click(); // worked. the click is triggered upon this.name
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/uikit/2.27.5/css/uikit.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/uikit/2.27.5/js/uikit.min.js"></script>
<div id="app" class="container">
<div class="uk-grid" uk-grid>
<div v-for="r in li_address">
<label>{{r.name}}
<input :id="r.name" :ref="r.name" type="radio" class="uk-radio" :value="r"
name="address_group">
</label>
</div>
</div>
</div>
Add a ref to your element called myBtn like :
<div ref="myBtn" >some content</div>
then run the click :
this.$refs.myBtn.click()
example :
Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue({
el: '#app',
methods: {
logOk() {
console.log("OK OK")
}
},
mounted() {
this.$refs.okBtn.click()
}
})
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app" class="container">
<button ref="okBtn" #click="logOk"> OK</button>
</div>
Just select your element and trigger Click Event on Mounted life cycle of Vue app
mounted() {
this.$nextTick(() => {
document.getElementById('myBtn').click()
});
}
$nextTick according to VueJs documentation :
Defer the callback to be executed after the next DOM update cycle. Use
it immediately after you’ve changed some data to wait for the DOM
update.
In your example code, there is no need for any DOM manipulation. The main strength of a declarative reactive framework like Vue is for changes to the model to be automatically propagated to the view. This will select the appropriate radio button just by setting v-model appropriately.
new Vue({
el: '#app',
data() {
return {
li_address: [{name: 'CA'}, {name: 'NY'}, {name: 'AL'}],
name: 'NY'
}
}
})
<div id="app" class="container">
<div class="uk-grid" uk-grid>
<div v-for="r in li_address">
<label :for="r.name">{{r.name}}
<input type="radio" v-model="name" :id="r.name" :value="r.name">
</label>
</div>
<h4>NAME: {{ name }}</h4>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/uikit/2.27.5/css/uikit.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/uikit/2.27.5/js/uikit.min.js"></script>
I'm reading through the documentation here for switch style checkboxes: https://bootstrap-vue.org/docs/components/form-checkbox
When I use the example HTML/JS in my own application, I can get the html to render but it doesn't show the actual switch toggle, like so:
https://jsfiddle.net/Lz5tcpqb/2/
<template>
<div>
<b-form-checkbox v-model="checked" name="check-button" switch>
Switch Checkbox <b>(Checked: {{ checked }})</b>
</b-form-checkbox>
</div>
</template>
<script>
export default {
data() {
return {
checked: false
}
}
}
</script>
Is there something I'm missing here?
It's kind of working, you might need to import css or use latest stable version of bootstrap-vue and Vue.js
new Vue({
el: '#app',
data() {
return {
checked: false,
};
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link href="https://unpkg.com/bootstrap#4.5.2/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue#2.16.0/dist/bootstrap-vue.css" rel="stylesheet" />
<script src="https://unpkg.com/bootstrap-vue#2.16.0/dist/bootstrap-vue.js"></script>
<div id="app">
<b-form-checkbox v-model="checked" name="check-button" switch>
Switch Checkbox <b>(Checked: {{ checked }})</b>
</b-form-checkbox>
</div>