Dynamically disable option in Vuetify overflow component - vue.js

Vuetify disabled prop directly disabled input itself.I am trying to disable individual select option as per content on page.If we pass disabled="string" to items array (static arrangement).
How to make it dynamic.I have made Codepen for the same https://codepen.io/spider007/pen/eYmLBOG
<div id="app">
<v-app id="inspire">
<v-container>
<v-overflow-btn
class="my-2"
:items="items"
label="Overflow Btn - Dense"
dense
v-model="recordToAdd"
></v-overflow-btn>
<p v-if =" recordToAdd === '1' ">A's content is here -- i.e, Option A must be disabled in selection option</p>
</v-container>
</v-app>
</div>
JS
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
recordToAdd : "",
items: [
{text:"A",value:"1"},
{text:"B",value:"2"},
{text:"C",value:"3"},
],
}),
})

You just need to add disabled: true in the data.
<template>
...
<v-overflow-btn
class="my-2"
:items="dropdown"
label="Test"
segmented
target="#dropdown-example"
/>
...
</template>
...
data() {
return {
disabled: false,
dropdown: [
// Always disabled
{ text: 'disabled option', callback: () => console.log('disabled'), disabled: true },
// disable depending on another variable
{ text: 'depending', callback: () => console.log('Hello'), disabled: this.disabled },
{ text: 'other Option', callback: () => console.log('Option') },
]
}
},

Related

Vuetify v-data-table custom filter for dropdown

I have a v-data-table that already has the :search and :sort-by enabled. I have now created a select where I pull in my status from VueX. Accepted, Rejected. What I want to do is not only search or sort but when selecting from the drop down, accepted only the accepted values display in the table.
<v-select
v-model="selectStatus"
label="Status"
:items="statusData"
item-value="id"
item-text="name"
return-object
#change="filterStatus"
/>
Is this the correct way to setup the filter?
methods: {
filterStatus () {
console.log('This is where I am planning to add my custom filter')
}
}
This is my statusData:
userStatus : [
{
id: 0,
name: "Accepted",
},
{
id: 1,
name: " Rejected",
},
];
Or better to pass in the data:
{ text: 'Status', value: 'status.name', filter: value => {}},
To disable certain values to be selected add a disabled property to your items.
var app = new Vue({
el: '#app',
vuetify: new Vuetify(),
data: {
items: [{
id: 0,
name: 'Accepted'
},
{
id: 1,
name: ' Rejected',
disabled: true
}
],
value: null
}
})
<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.6.0"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-container>
Value : {{value}}
<v-select
v-model="value"
label="Status"
:items="items"
item-value="id"
item-text="name"
return-object
/>
</v-container>
</v-app>
</div>
Documentation : props-disabled

Reset select values in v-autocomplete, in order to add multiple items

I'm creating an application that has a selection box to choose between some template data. However, the user should be able to select the same template option several times and, each time he selects the template, a new informational box appears in the screen.
My problem is that the v-autocomplete component doesn't enable this kind of behavior: we can select one option (or multiple options), but not the same option twice.
I thought about making something like this: every time the user selects the option A, the infobox would appear below and the component would reset to a empty option. Then, the user could choose option A again and, when he chooses it, another info box would appear, how many times the user needs it.
How could I do something like this using vue? I didn't found any component that would do something like this on default, so I think I'll have to tweak the component behavior, but I don't know exactly where to start.
My template:
<template>
<div class="select-wrapper" id="selectBox">
<v-autocomplete
class="select-input"
:items="items"
:name="label"
placeholder="select item"
solo
:value="value"
#change="$event => onChange($event, items)"
item-text="name"
item-value="value"
:required="required"
:rules="[
value =>
!required ||
!!value ||
"required"
]"
></v-autocomplete>
</div>
</template>
And my Vue code:
<script lang="ts">
import { defineComponent } from "#vue/composition-api";
import Vue from "vue";
interface SelectItem {
name: string,
value: string
}
interface SelectBoxProps {
items: SelectItem[];
value: string;
onSelect: ({ target }: { target?: SelectItem }) => void;
hasResetSelection: boolean;
}
export default defineComponent({
name: "SelectBox",
props: {
label: String,
items: Array,
value: [String, Number],
onSelect: Function,
disabled: Boolean,
required: {
type: Boolean,
default: false
},
hasError: Boolean,
errorMessage: String,
hasResetSelection: {
type: Boolean,
default: false
}
},
directives: {
ClickOutside
},
setup({ onSelect, hasResetSelection }: SelectBoxProps) {
const onChange = (selectedValue: string, itemsArr: SelectItem[]) => {
const targetItem = itemsArr.find(i => i.value === selectedValue);
if (hasResetSelection) {
Vue.nextTick(() => {
console.log("onselect should reset value");
return onSelect({ target: { name: "", value: "" } });
});
}
return onSelect({ target: targetItem });
};
return {
onChange
};
}
});
</script>
This was my last attempt with Vue.nextTick, I already tried to tweak the component with ref() and it didn't work as well. Do you have any suggestions?
You can use another variable just to hold the input for the autocomplete component Like this:
var app = new Vue({
el: '#app',
vuetify: new Vuetify(),
data: {
items: [{ name : 'hello', value : 1 }, { name : 'world', value : 2 }],
value : null,
values : []
},
methods: {
onChange() {
this.values.push(this.value)
this.$nextTick(() => {
this.value = null
})
},
}
})
<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.6.0"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app>
<v-container>
Values : {{values}}
<v-autocomplete
:items="items"
placeholder="select item"
solo
v-model="value"
item-text="name"
item-value="value"
#change="onChange"
/>
</v-container>
</v-app>
</div>

Data lost on vue dynamic component when back to parent component

I'm using Vue-form-wizard to create multi-step form. in one of the steps, I'm loading a dynamic component, and pass the data using v-bind and props to dynamic component. the data updates prefectly when we are on the dynamic component, but when I go to the next step all the changes lost on and rests to the parent component defaults! I tried but that doesn't do anything. here is the example of what happens:
the html:
<div id="app">
<div>
<form-wizard #on-complete="onComplete">
<tab-content v-for="tab in tabs"
v-if="!tab.hide"
:key="tab.title"
:title="tab.title"
:icon="tab.icon">
<component :is="tab.component" v-bind={'form':form}></component>
</tab-content>
</form-wizard>
</div>
</div>
and the js will be:
Vue.use(VueFormWizard)
Vue.component('step1', {
template:` <div> My first tab content <br>
</div>`,
props:['form'],
created(){
this.form = 'that other form';
alert(this.form);
}
}
)
Vue.component('step2', {
template:`<div> My second tab content </div>`
})
Vue.component('step3', {
template:`<div> My third tab content </div>`
})
Vue.component('step4', {
template:`<div> Yuhuuu! This seems pretty damn simple </div>`
})
new Vue({
el: '#app',
data() {
return {
form:'this form',
tabs: [{title: 'Personal details', icon: 'ti-user', component: 'step1'},
{title: 'Is Logged In?', icon: 'ti-settings', component: 'step2', hide: false},
{title: 'Additional Info', icon: 'ti-location-pin', component: 'step3'},
{title: 'Last step', icon: 'ti-check', component: 'step4'},
],
}
},
methods: {
onComplete: function(){
alert(this.form);
}
}
})
please help me.
thanks alot
Here:
props:['form'],
created(){
this.form = 'that other form';
alert(this.form);
}
you are changing a prop. Don't do that.
All props form a one-way-down binding between the child property and
the parent one: when the parent property updates, it will flow down to
the child, but not the other way around. This prevents child
components from accidentally mutating the parent’s state, which can
make your app’s data flow harder to understand.
Instead, the child should emit an event that the parent acts on to update the data item. I like to create a computed in the child to wrap up that behavior so I can treat it like a variable that I can assign to.
In the snippet below, I use the .sync modifier to make the update clean. I also call $nextTick after setting the value to give the event time to be handled.
Vue.use(VueFormWizard)
Vue.component('step1', {
template: ` <div> My first tab content <br>
</div>`,
props: ['form'],
computed: {
proxyForm: {
get() {
return this.form;
},
set(v) {
this.$emit('update:form', v);
}
}
},
created() {
this.proxyForm = 'that other form';
this.$nextTick(() =>
alert(this.proxyForm));
}
})
Vue.component('step2', {
template: `<div> My second tab content </div>`
})
Vue.component('step3', {
template: `<div> My third tab content </div>`
})
Vue.component('step4', {
template: `<div> Yuhuuu! This seems pretty damn simple </div>`
})
new Vue({
el: '#app',
data() {
return {
form: 'this form',
tabs: [{
title: 'Personal details',
icon: 'ti-user',
component: 'step1'
},
{
title: 'Is Logged In?',
icon: 'ti-settings',
component: 'step2',
hide: false
},
{
title: 'Additional Info',
icon: 'ti-location-pin',
component: 'step3'
},
{
title: 'Last step',
icon: 'ti-check',
component: 'step4'
},
],
}
},
methods: {
onComplete: function() {
alert(this.form);
}
}
});
<script src="https://unpkg.com/vue#latest/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-form-wizard#0.8.4/dist/vue-form-wizard.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vue-form-wizard#0.8.4/dist/vue-form-wizard.min.css" rel="stylesheet" />
<div id="app">
<div>
<form-wizard #on-complete="onComplete">
<tab-content v-for="tab in tabs" v-if="!tab.hide" :key="tab.title" :title="tab.title" :icon="tab.icon">
<component :is="tab.component" :form.sync="form"></component>
</tab-content>
</form-wizard>
</div>
</div>

Setting v-select value programmatically does not fire #change in vuetify

I am trying to set v-select value programmatically, however the associated #change event does not fire. If I manually select the option, the event fires as expected.
Template:
<div id="app">
<v-app dark>
<v-select
v-model="currentItem"
:items="items"
#change="itemChanged"
/>
</v-app>
</div>
JS:
Vue.use(Vuetify);
var vm = new Vue({
el: "#app",
methods: {
itemChanged(item) {
console.log('item changed',item);
}
},
data: {
currentItem: '',
items: [
{ text: "Name", value: 'name' },
{ text: "Number", value: 'number' },
{ text: "Inputs", value: 'inputs' }
]
},
mounted() {
setTimeout(() => {
this.currentItem = 'inputs';
}, 2000);
}
});
The jsfiddle is here
Does anybody have any solutions aside from manually calling the function when setting the value programmatically?
The change event is defined in such a way so it is emitted when the input is changed by user interaction (see the event documentation). If you want to monitor all the changes, you can either use the input event:
<v-select
v-model="currentItem"
:items="items"
#input="itemChanged"/>
https://jsfiddle.net/0qbomzta/
or add a watcher to watch the currentItem:
<div id="app">
<v-app dark>
<v-select
v-model="currentItem"
:items="items"/>
</v-app>
</div>
In Vue instance, add:
watch: {
currentItem (newVal) {
console.log('item changed', newVal);
}
},
https://jsfiddle.net/w5voub3h/

Vue.js directive within a template

Based on this example https://vuejs.org/examples/select2.html
I try to create component for reuse in a future.
Unfortunately, my code doesn't work.
HTML:
<template id="my-template">
<p>Selected: {{selected}}</p>
<select v-select="selected" :options="options">
<option value="0">default</option>
</select>
</template>
<div id="app">
<my-component></my-component>
</div>
Vue:
Vue.component('my-component', {
template: '#my-template'
})
Vue.directive('select', {
twoWay: true,
priority: 1000,
params: ['options'],
bind: function () {
var self = this
$(this.el)
.select2({
data: this.params.options
})
.on('change', function () {
self.set(this.value)
})
},
update: function (value) {
$(this.el).val(value).trigger('change')
},
unbind: function () {
$(this.el).off().select2('destroy')
}
})
var vm = new Vue({
el: '#app',
data: {
selected: 0,
options: [
{ id: 1, text: 'hello' },
{ id: 2, text: 'what' }
]
}
})
https://jsfiddle.net/xz62be63/
Thank you for any help!
your problem has nothing to do with the directive itself.
selected and options is defined in the data of your Vue main instance, not in the data of my-component - so it's not available in its template.
But you can pass it from the main instance to the component using props:
<div id="app">
<my-component :selected.sync="selected" :options="options"></my-component>
<!-- added the .sync modifier to transfer the value change back up to the main instance-->
</div>
and in the code:
Vue.component('my-component', {
template: '#my-template',
props: ['selected','options']
})
updated fiddle: https://jsfiddle.net/Linusborg/rj1kLLuc/