Activity indicator not loading correctly in Vuetify - vue.js

new Vue({
el: '#app',
vuetify: new Vuetify({
theme: {
dark: true
},
}),
data() {
return {
loading: null,
requests: [{"req_id":78},{"req_id":79}],
tableHeaders: [
{
text: 'ID',
value: 'req_id',
align: 'center',
},
{ text: 'Actions', value: 'action', sortable: false, align: 'center'},
],
createloading: false,
cancelloading: false,
};
},
methods: {
createPacks(item) {
this.loading = !this.loading;
item.createloading = true;
},
excludeRequest(item) {
this.loading =!this.loading;
item.createloading = false;
},
}
})
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vuetify/dist/vuetify.min.js"></script>
<link href="https://unpkg.com/vuetify/dist/vuetify.min.css" rel="stylesheet"/>
<div id="app">
<v-app>
<v-row no-gutters class="align-start justify-start">
<v-col>
<v-row>
<v-data-table
:headers="tableHeaders"
:items="requests"
:loading="loading"
>
<template v-slot:item.action="{ item }">
<v-btn color="success" #click="createPacks(item)" :loading="item.createloading" :disabled="item.createloading">Create</v-btn>
<v-btn color="error" #click="excludeRequest(item)" :loading="item.cancelloading" :disabled="!item.createloading">Cancel</v-btn>
</template>
</v-data-table>
</v-row>
</v-col>
</v-row>
</v-app>
</div>
Please help me implement this code correctly, as it does not function correctly. The buttons should correctly show the loading indicator and should be independent.
Thank you in advance for your generosity.
Below is a link to codepen.
https://codepen.io/protemir/pen/MWwGaeO

Related

How to enable a disabled text-field with click

I have two text-field in Vuetify, I want that when I click on one of them, the other one is disabled, so far I have managed to make it happen, but, I want that when I click on the disabled one, the text is enabled and disabled again previous-field.
This is the code of the component:
<v-row
v-for="(f, index) in fieldsFilter"
:key="index+'formfilterkey'"
class="pa-0 ma-0"
>
<template v-slot:activator="{ on, attrs }">
<v-text-field
v-model="f.value"
:label="f.label"
:disabled="f.disabled"
v-on:click="f.onClick"
readonly
clearable
dense
v-bind="attrs"
:rules="f.rule"
outlined
:required="f.required"
class="mx-3"
v-on="on"
/>
And the textfield properties are generated from another file.
created() {
this.fieldsFilterControl=[
{
type: "datepicker",
label: "Range 1",
value: null,
range: true,
menu: false,
disabled: 0,
onClick: ()=> {
this.fieldsFilterControl[1].disabled = true
}
},
{
type: "monthpicker",
label: "Range 2",
value: null,
range: true,
menu: false,
disabled: false,
onClick: ()=> {
this.fieldsFilterControl[0].disabled = true
}
},
],
Disabling a control also disables its events (it's by design).
I have a question for you - Does the text-field truly need to be disabled ?
As user can edit one text field at a time and this is how it will work if you disabled as well (as per your requirement).
Solution : You can add a toggle button against a disabled text field and on click of that button you can enable the specific text field and disable another one.
Live Demo :
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
fieldsFilter: [
{
type: "datepicker",
label: "Range 1",
value: null,
range: true,
menu: false,
disabled: false
},
{
type: "monthpicker",
label: "Range 2",
value: null,
range: true,
menu: false,
disabled: false
}
]
}),
methods: {
onEnableDisable(index) {
this.fieldsFilter.forEach((obj, i) => {
obj.disabled = i === index ? false : true
});
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vuetify#2.6.10/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/vuetify#2.6.10/dist/vuetify.min.css"/>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"/>
<div id="app">
<template>
<v-container class="grey lighten-5">
<v-row v-for="(f, index) in fieldsFilter"
:key="index"
class="pa-0 ma-0">
<v-col sm="4">
<v-text-field
v-model="f.value"
:label="f.label"
:disabled="f.disabled"
v-on:click="onEnableDisable(index)"
outlined
/>
</v-col>
<v-col>
<v-btn v-if="f.disabled" #click="onEnableDisable(index)">Enable Me</v-btn>
</v-col>
</v-row>
</v-container>
</template>
</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

How to change the cursor default to pointer in Vuetify component

I want to change cursor default to pointer when active autocomplete in Vuetify.
I tried to make css code to change cursor.
but mouse drag on the autocomplete bottom, cursor change "text" style like "I beem". I want to show the "pointer " style.
I couldn't find out any idea Vuetify web site.
Does anyone have idea?
<template>
<v-card>
<v-container fluid>
<v-row
align="center"
>
<v-col cols="12">
<v-autocomplete
v-model="value"
:items="items"
dense
filled
label="Filled"
class="test_cursor"
></v-autocomplete>
</v-col>
</v-row>
</v-container>
</v-card>
</template>
<script>
export default {
data: () => ({
items: ['foo', 'bar', 'fizz', 'buzz'],
values: ['foo', 'bar'],
value: null,
}),
}
</script>
<style lang="scss" scoped>
.test_cursor{
cursor: pointer;
}
</style>
By default cursor is set to text (which appears as the "I-beam" you mention), but you can change the v-autocomplete's cursor by targeting the input in your CSS:
.test_cursor input {
cursor: pointer;
}
new Vue({
vuetify: new Vuetify(),
el: '#app',
data () {
return {
states: [
{ name: 'Florida', abbr: 'FL', id: 1 },
{ name: 'Georgia', abbr: 'GA', id: 2 },
{ name: 'Nebraska', abbr: 'NE', id: 3 },
{ name: 'California', abbr: 'CA', id: 4 },
{ name: 'New York', abbr: 'NY', id: 5 },
],
}
},
})
.test_cursor input {
cursor: pointer;
}
<script src="https://unpkg.com/vue#2.6.11"></script>
<script src="https://unpkg.com/vuetify#2.3.5"></script>
<link rel="stylesheet" href="https://unpkg.com/vuetify#2.3.5/dist/vuetify.css">
<v-app id="app">
<v-autocomplete
class="test_cursor"
:items="states"
item-text="name"
label="State"
></v-autocomplete>
</v-app>

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

Display fields compared of a value

I have a number (size) field that can range from 0 to 7. I also have an intensity object that has 2 fields (in and out) I would like to display the number of objects in relation to the number in the number +1 field
What method can I use to solve my problem ?
I made a JSFiddle if someone have a solution for me .
https://jsfiddle.net/sebastianczech/2wfapuv4/61/
I also need, when I check the 'In = Out' checkbox, to attribute to 'Out' the same value than 'In'.
<link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet" type="text/css">
<div id="app">
<v-app >
<h1>Selection</h1>
<div v-for="car in cars">
<v-select
label="Selection"
:items="car.version"
item-text="color"
>
</v-select>
<v-text-field
label="Size"
type="number"
min="1"
max="8"
v-model="sizeValue">
</v-text-field>
<div v-for="(int, index) in intensity">
<v-text-field
label="In"
type="number"
min="1"
max="100"
v-model="int.in">
</v-text-field>
<v-text-field
label="Out"
type="number"
min="1"
max="100"
v-model="int.out">
</v-text-field>
</div>
</div>
<v-checkbox label="Apply to All" v-model="checkboxAll"></v-checkbox>
<v-checkbox label="In = Out" v-model="checkboxInOut"></v-checkbox>
</v-app>
</div>
Vue.use(Vuetify);
var vm = new Vue({
data() {
return {
checkboxInOut: false,
checkboxAll: false,
sizeValue: null,
intensity:[
{in: void 0, out:void 0}],
cars: [
{
name: 'McQueen',
version: [
{color: 'blue' },
{color: 'red' },
{color: 'green' },
{color: 'purple' },
]
}
],
}
},
methods: {
}
})
Added fixes to the above code
working codepen here: https://codepen.io/chansv/pen/KKKvrom?editors=1010
<div id="app">
<v-app id="inspire">
<v-container fluid>
<h1>Selection</h1>
<div v-for="car in cars">
<v-select
label="Selection"
:items="car.version"
item-text="color"
>
</v-select>
<v-btn #click="addIntensity">
add intensity
</v-btn>
<br>
<br>
</v-text-field>
<div v-for="(int, index) in intensity">
index{{index}}
<v-btn #click="delIntensity(index)">
delete intensity
</v-btn>
<v-text-field
label="In"
type="number"
min="1"
max="100"
v-model="int.in">
</v-text-field>
<v-text-field
label="Out"
type="number"
min="1"
max="100"
v-model="int.out">
</v-text-field>
</div>
</div>
<v-checkbox label="Apply to All" v-model="checkboxAll"></v-checkbox>
<v-checkbox label="In = Out" v-model="checkboxInOut"></v-checkbox>
</v-container>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
checkboxInOut: false,
checkboxAll: false,
sizeValue: 0,
intensity:[
{in: 0, out: 0}],
cars: [
{
name: 'McQueen',
version: [
{color: 'blue' },
{color: 'red' },
{color: 'green' },
{color: 'purple' },
]
}
],
}),
methods: {
addIntensity() {
this.$set(this.intensity, this.intensity.length, {in: 0, out: 0});
},
delIntensity(index) {
this.intensity.splice(index, 1);
}
},
created() {
for(var i = 0; i <= val;i++){
this.$set(this.intensity, i, {in: 0, out: 0});
}
},
watch: {
checkboxInOut(val) {
if (val) {
this.intensity.forEach(x => {
x.out = x.in;
});
}
}
}
})