Vuetify Vuex v-for v-switch default true - vue.js

I have a list of values in the Vuex store that I create v-switches for but I would like for the default value of the v-switch to be true on creation. I have tried input-value="true" but it does nothing. Any ideas how to set them to true since I can not find anything in the documentation that helps me?
<v-switch
v-for="(layerg, k) in getAddedGeoMetLayers"
:key="k"
:label="layerg"
:value="layerg"
dense
hide-details
v-model="selectedGeometLayers"
#change="updateSelectedAddedGeoMetLayers"
></v-switch>
export default {
mounted () {
this.selectedGeometLayers = this.getSelectedAddedGeometLayers
},
data () {
return {
selectedGeometLayers: []
}
},
computed: {
...mapGetters('map', [
'getSelectedAddedGeometLayers'
])
},
methods: {
updateSelectedAddedGeoMetLayers: function () {
this.$store.dispatch('map/updateSelectedAddedGeometLayers', this.selectedGeometLayers)
}
}

You need to set selectedValues Array to equal the getArray - this way all the v-switch will be selected at the beginning:
mounted() {
this.selectedValues = [...this.getArray]
}

From the docs, it looks like you can set the model to have every item in your array.
From: https://vuetifyjs.com/en/components/switches/#model-as-array
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
people: ['John', 'Jacob'],
}
},
})
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app id="inspire">
<v-container fluid>
<p>{{ people }}</p>
<v-switch
v-model="people"
color="primary"
label="John"
value="John"
></v-switch>
<v-switch
v-model="people"
color="primary"
label="Jacob"
value="Jacob"
></v-switch>
</v-container>
</v-app>
</div>

Related

prevent a specific chip to be deleted from combobox

I have these combobox chips with a prob deletable-chips
<v-combobox
v-model="selectedCategories"
:items="attributeCategories"
item-text="name"
item-value="id"
label="Category"
multiple
chips
clear-icon="mdi-close-circle"
deletable-chips
v-on:change="changeCategory(selectedCategories)"
></v-combobox>
Is there a way to prevent a specific chip to be deleted? For example not show the remove button on a specific one? Let's say for Device and only allow Weather and Geo Location to me removed
Instead of using in-built delete method of v-chips. You can do the implementation via custom #click:close event. I created a working demo for you :
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
model: [],
items: [
{
text: 'Weather'
},
{
text: 'Geo Location'
},
{
text: 'Device'
}
]
}),
methods: {
remove (itemText) {
if (itemText === 'Device') {
return;
} else {
this.model.forEach(obj => {
if (obj.text === itemText) {
this.model.splice(this.model.indexOf(obj), 1)
}
})
this.model = [...this.model]
}
}
}
})
<script src="https://unpkg.com/vue#2.x/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify#2.6.6/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/vuetify#2.6.6/dist/vuetify.min.css"/>
<link rel="stylesheet" href="https://unpkg.com/#mdi/font#6.x/css/materialdesignicons.min.css"/>
<div id="app">
<v-app id="inspire">
<v-container fluid>
<v-combobox
v-model="model"
:items="items"
label="Select"
multiple
small-chips
>
<template v-slot:selection="{ attrs, item, parent, selected }">
<v-chip
v-bind="attrs"
:input-value="selected"
close="false"
#click:close="remove(item.text)"
>
<span class="pr-2">
{{ item.text }}
</span>
</v-chip>
</template>
</v-combobox>
</v-container>
</v-app>
</div>

Vue watch on objects

I'm using Vue2 and I have a problem to compare objects. But when compare "newVal" and "oldVal" values are always the same.
Child componenet:
name: "List",
components: {
Pagination, UserDetails
},
props: {
filters: Object
},
watch: {
filters: {
handler(val, oldVal) {
console.log(JSON.stringify(val));
console.log(JSON.stringify(oldVal));
},
deep: true,
}
},
Parent Componenet:
<template>
<div>
<b-form inline>
<label class="sr-only" for="inline-form-input-name">Name</label>
<b-form-input
id="inline-form-input-name"
class="mb-2 mr-sm-2 mb-sm-0"
v-model="filters.username"
placeholder="Name"
></b-form-input>
<label class="sr-only" for="inline-form-input-username">Email</label>
<b-input-group class="mb-2 mr-sm-2 mb-sm-0">
<b-form-input
id="inline-form-input-username"
v-model="filters.email"
placeholder="Email"></b-form-input>
</b-input-group>
<b-button variant="danger">Clear</b-button>
</b-form>
<List :filters="filters"/>
</div>
</template>
<script>
import List from "./List";
export default {
name: "AdminUserList",
components: {
List,
},
data() {
return {
filters: {
username: '',
email: ''
},
}
},
}
</script>
<style lang="scss">
</style>
Result:
{"username":"d","email":""}
{"username":"d","email":""}
from the official doc you will find:
Note: when mutating (rather than replacing) an Object or an Array, the old value will be the same as new value because they reference the same Object/Array. Vue doesn’t keep a copy of the pre-mutate value.
vue js watcher DOC
one thing that you can do is to watch the object's property directly like:
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
filters: {
name: '',
email: '',
},
};
},
watch: {
'filters.name' (newVal, oldVal) {
console.log(`new name: ${newVal}`, `, old name: ${oldVal}`);
},
'filters.email' (newVal, oldVal) {
console.log(`new email: ${newVal}`, `, old email: ${oldVal}`);
},
},
});
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<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>
<div id="app">
<v-app>
<v-container>
<v-row class="px-5">
<v-text-field v-model="filters.name" outlined label="name"></v-text-field>
</v-row>
<v-row class="px-5">
<v-text-field v-model="filters.email" outlined label="email"></v-text-field>
</v-row>
</v-container>
</v-app>
</div>
Try to adjust watcher accordingly
watch: {
filters: {
handler: function(val, oldVal) {
console.log(JSON.stringify(val));
console.log(JSON.stringify(oldVal));
},
deep: true,
}
},
I have just followed documentation from the official website

vuetify v-alert incorrectly dismissing sibling when transition is applied

I am using vuetify v-alert with v-for=alert in alerts looping through alerts array, when an alert is dismissed #input event is fired and I'm removing it from alerts array.
The problem I am facing, that when the element is clicked, transition is applied, and the sibling alert is now shown at the position where the one which was dismissed, seems like the click event is fired for the sibling element as well and the sibling v-alert is isVisible == false but the #input event is not fired.
If I remove transition="scroll-y-reverse-transition" from the v-alert it works properly.
Why is this happening?
const alertsComponent = {
name: "MyAlertsComponent",
template: "#alerts",
data() {
return {
alerts: []
};
},
created() {
this.$root.$off("alert");
this.$root.$on("alert", this.addAlert);
},
methods: {
closeAlert(idx, alert) {
console.log(`deleting alert idx: ${idx} - ${alert}`);
this.$delete(this.alerts, idx);
},
addAlert(alert, ...args) {
alert.type = alert.type || "error";
this.alerts.unshift(alert);
}
}
};
const app = new Vue({
el: "#app",
vuetify: new Vuetify(),
components: {
alertsComponent
},
mounted() {
[...Array(8).keys()].forEach((e) => {
this.fireAlert(this.counter++);
});
},
methods: {
fireAlert(val = this.counter++) {
const alert = this.generateAlert(val);
this.$root.$emit("alert", alert);
},
generateAlert(val, type = "error") {
return {
val,
type
};
}
},
data() {
return {
counter: 1
};
}
});
.alert-section {
max-height: 400px;
padding: 5px;
}
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app>
<v-main>
<v-container>
<header>VueTify!</header>
<hr>
<v-row>
<v-col>
<v-btn #click="fireAlert()">Add Alert</v-btn>
</v-col>
</v-row>
<alerts-component>Hi</alerts-component>
</v-container>
</v-main>
</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>
<template id="alerts">
<div>
<div class="alert-section overflow-y-auto">
<v-alert v-for="(alert, index) in alerts" :key="index" dense dismissible elevation="5" text :type="alert.type" #input="closeAlert(index, alert)" #addAlert="addAlert"
transition="scroll-y-reverse-transition"
>
{{ alert.val }}
</v-alert>
</div>
<hr>
<pre class="code">{{ JSON.stringify(alerts, null, 2) }}
</pre>
</div>
</template>
Looks like the problem is using the index as key.
If I change :key="alert.val" it works fine.

How to add a custom button in vuetify select

I have a scenario like I have to list a few hundred categories and I have to show them in a select box. Since the list is huge, skip and limit is implemented in the backend, so that it will limit the categories to 20s. My case is like when the user sees the first 20 categories, in the end, I have to add some button stating like 'Load more' so that when the user clicks on it, they can see the next 20 categories. But I have no idea how to add a button in a vuetify select. Can someone help me with this?
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
fruits: [
'Item 1',
'Item 2',
'Item 3',
'Item 4'
],
selectedFruits: [],
}),
computed: {
likesAllFruit () {
return this.selectedFruits.length === this.fruits.length
},
likesSomeFruit () {
return this.selectedFruits.length > 0 && !this.likesAllFruit
},
icon () {
if (this.likesAllFruit) return 'mdi-close-box'
if (this.likesSomeFruit) return 'mdi-minus-box'
return 'mdi-checkbox-blank-outline'
},
},
methods: {
toggle () {
this.$nextTick(() => {
if (this.likesAllFruit) {
this.selectedFruits = []
} else {
this.selectedFruits = this.fruits.slice()
}
})
},
loadMore () {
console.log('load more ...')
}
},
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.2.26/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.2.26/dist/vuetify.min.js"></script>
<div id="app">
<v-app id="inspire">
<v-container fluid>
<v-select
v-model="selectedFruits"
:items="fruits"
label="Favorite Fruits"
multiple
>
<template v-slot:prepend-item>
<v-list-item
ripple
#click="toggle"
>
<v-list-item-action>
<v-icon :color="selectedFruits.length > 0 ? 'indigo darken-4' : ''">{{ icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>Select All</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-divider class="mt-2"></v-divider>
</template>
<template v-slot:append-item>
<v-divider class="mb-2"></v-divider>
<v-btn color="primary" #click="loadMore">
Click me for load more items.
</v-btn>
</template>
</v-select>
</v-container>
</v-app>
</div>
In Vuetify 2.x there is an virtual scroll component, but I still found the v-intersect easiest to use...
markup:
<v-autocomplete
v-model="selected"
:items="beers"
item-text="name"
item-value="id"
label="Search da beers.."
return-object
autocomplete="off"
>
<template v-slot:append-item>
<div v-intersect="onIntersect" class="pa-4 teal--text">
Loading more items ...
</div>
</template>
</v-autocomplete>
data() {
return {
beers: [],
selected: null,
perPage: 30,
page: 1,
}
},
methods: {
getBeers() {
console.log('page', this.page)
const apiUrl = `https://api.punkapi.com/v2/beers?page=${this.page}&per_page=${this.perPage}`
axios.get(apiUrl)
.then(response => {
this.beers = [
...this.beers,
...response.data
]
})
},
onIntersect () {
console.log('load more...')
this.page += 1
this.getDate()
},
},
created() {
this.getData()
}
Working Codeply

How to change theme light(default) in Vuetify 2.x in CDN mode?

there is another similar topic here but i think that answer is not updated , if you see the codepen in that link is not working anymore , im trying to change the theme without having to add color atributte always on each component , i just want to define the theme color and continue coding the design , i did this trying to change on created method the theme color but is not working .
im using just cdns no vue-cli , no Vue.use like the other topic , i think the other topic was resolved but in vuetify 2.x that answer doesnt fit. thanks.
//JAVASCRIPT
var vuetify = new Vuetify ({
theme: {
primary: '#9e9e9e',
secondary: '#000000',
accent: '#8c9eff',
error: '#ff00ff'
}
});
new Vue({
el: '#app',
vuetify : vuetify,
data: () => ({
}),
methods: {
},
created(){ this.$vuetify.theme.primary = '#ff00ff';
}
});
<!-- HTML -->
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet"/>
<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>
<div id="app">
<v-app>
<v-content>
<v-container grid-list-xl>
<v-btn class='rounded'>Default</v-btn>
<v-btn class='rounded'>Primary</v-btn>
<v-btn class='rounded'>Secondary</v-btn>
<v-btn class='rounded'>Accent</v-btn>
<v-btn class='rounded'>Error</v-btn>
</v-container>
</v-content>
</v-app>
</div>
You can use this.$vuetify.theme.dark = true; in your created method
If you want to customize the theme, you need to specify which theme (themes.theme.dark)
//JAVASCRIPT
const vuetify = new Vuetify({
theme: {
themes: {
dark: {
primary: '#9e9e9e',
secondary: '#000000',
accent: '#8c9eff',
error: '#ff00ff'
},
},
},
})
new Vue({
el: '#app',
vuetify : vuetify,
data: () => ({
}),
created(){
this.$vuetify.theme.dark = true;
}
});
<!-- HTML -->
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-content>
<v-container grid-list-xl>
<v-btn class='rounded'>Default</v-btn>
<v-btn class='rounded primary'>Primary</v-btn>
<v-btn class='rounded secondary'>Secondary</v-btn>
<v-btn class='rounded accent'>Accent</v-btn>
<v-btn class='rounded error'>Error</v-btn>
</v-container>
</v-content>
</v-app>
</div>