v-select allows to add append-outer-icon but how to force to expand icon list when this item is clicked?
<v-select
:items="selectItems.position"
v-model="selectedPosition"
clear-icon="highlight_remove"
append-icon="unfold_more"
append-outer-icon="unfold_more"
#click:append-outer="openSelect"
>
#click:append-outer allows add a callback function but what i have do in openSelect to expand the item's list?
You should add a ref to your v-select element. And then use this ref into your openSelect function:
<template>
<v-select
ref="theSelect"
:items="selectItems.position"
v-model="selectedPosition"
clear-icon="highlight_remove"
append-icon="unfold_more"
append-outer-icon="unfold_more"
#click:append-outer="openSelect"
/>
</template>
<script>
export default {
methods: {
openSelect () {
this.$refs['theSelect'].onClick()
}
}
}
</script>
Related
I am in the process of migrating to vuetify3, and I'm using cypress (the cypress studio) for testing.
The <v-combobox> gives me a dropdown with items, but these are not easily referencable with css selectors. Cypress studio generates stuff like
cy.get('.v-overlay__content > .v-list > :nth-child(2) > .v-list-item__content > .v-list-item-title').click();
... which isn't readable for a human and will break if the dropdown list gets modified (for example, prepend a list item).
The best solution I came up with yet would be to give each list item a data-cy attribute; but how to do that properly? It seems to me that vuetify3 docs are still sparse on how to use the item slot (cf. https://next.vuetifyjs.com/en/components/combobox/); its workings seem to differ from vuetify2. By using the item slot like,
<v-combobox>
<template #item="scope">
myListItem
</template>
</v-combobox>
... the list items are not clickable any more.
Codesandbox: https://codesandbox.io/s/vuetify3-v-combobox-and-cypress-how-to-identify-list-items-gzfs71?file=/src/App.vue
EDIT Of course I could write the Cypress test code myself. But my premise is to use Cypress Studio, which CAN generate meaningful CSS selectors if possible, i. e. if there are id or data-cy attributes in the HTML code. But vuetify does not generate such. So I ask, how can I attach data-cy attributes to list items?
I think your selector is a bit more complex than needed
you can simplify to just the relevant elements
// get based on value
cy.get(".v-overlay-container .v-list-item").contains("Programming").click();
// get based on order (force: true is required if the combo box is still animating)
cy.get(".v-overlay-container .v-list-item").eq(2).click({ force: true });
example used
<template>
Click this combobox:
<v-combobox :items="items" id="combo" />
</template>
<script>
import { VCombobox } from "vuetify/components";
export default {
name: "App",
data() {
return {
items: ["Programming", "Design", "Vue", "Vuetify"],
};
},
components: { VCombobox },
};
</script>
test
describe("💩💩", () => {
beforeEach(() => {
cy.visit("http://10.0.0.248:8080/");
});
it("select with content", () => {
cy.get("#combo").click();
cy.get(".v-overlay-container .v-list-item").contains("Programming").click();
cy.get("#combo").should("have.value", "Programming");
});
it("select with order", () => {
cy.get("#combo").click();
cy.get(".v-overlay-container .v-list-item").eq(2).click({ force: true });
cy.get("#combo").should("have.value", "Vue");
});
});
I am using v-list-item-group to display a list of dynamic items (entities that can be created/deleted), of which can be selected to display more information about the selected item.
Up until this point, I have simply been using the model of v-list-item-group to determine which item has been selected.
<template>
<v-list>
<v-list-item-group v-model="listSelection">
<v-list-item v-for="(item, index) in items" :key="index">
</v-list-item>
</v-list-item-group>
</v-list>
</template>
<script>
export default {
props: {
value: Object
},
computed: {
items: function() {
return this.$store.state.items // Collection of entities from a server
},
listSelection: {
get: function() {
return this.items.indexOf(this.value)
},
set: function(newVal) {
this.$emit('input', this.items[newVal])
}
}
},
}
</script>
This approach works fine with the initial data set, as the first element in the list is the first object in items, etc. However, if I add an entity in the middle, or remove something, or simply cause one of the items to shift to a different position in the list, the index to item position becomes invalid. Essentially if the list adds a new element, regardless of its position, its value (when selected in the group) is the next highest unused value. For example:
let fruits = ['apple', 'carrot']
<v-list-item> for apple will have a value 0, and <v-list-item> for carrot will have a value 1.
fruits.splice(1, 0, "banana")
<v-list-item> for apple will have a value 0, <v-list-item> for banana will have a value 2, and <v-list-item> for carrot will have a value 1.
I've done a bunch of playing around with v-model and value in v-list-item-group, but have not figured out how to avoid this problem. I would be fine with adding an #click on my items, and having the items set a value, rather than computing based on the list, but I would like the list selection to be maintained based on the value.
As best as i've read, the documentation indicates that selection in lists should be handled using a v-list-item-group, but the component doesn't seem to support dynamic lists too well.
Upon additional inspection of the documentation, <v-list-item> supports a value prop, allowing <v-list-item-group to use a dictated value instead of the item index.
So the solution was to simply specify the items id as the value for each item, and then use the id as a means of managing the item group model.
<template>
<v-list>
<v-list-item-group v-model="listSelection">
<v-list-item v-for="(item, index) in items" :key="index" :value="item.id">
</v-list-item>
</v-list-item-group>
</v-list>
</template>
<script>
export default {
props: {
value: Object
},
computed: {
items: function() {
return this.$store.state.items; // Collection of entities from a server
},
listSelection: {
get: function() {
return this.value.id;
},
set: function(newVal) {
this.$emit('input', this.items.find(item => item.id === newVal));
}
}
},
}
</script>
I am working with v-Treeview. I want to set already selected children while loading this tree view. To do this, I added items in array and used this array in v-model. But It's not working. I have following implementations:
<template>
<v-container>
<v-treeview
:items="checklist"
selectable
return-object
dense
hoverable
:v-model="selectedItemList"
/>
</v-container>
</template>
<script>
export default {
name: 'WTreeView',
props: {
// Checklist of the selected card
checklist: {
type: Array,
required: true,
},
},
data() {
return {
selectedItemList: [],
};
},
created() {
this.selectedItemList.push(this.checklist[0]);
},
};
</script>
For "checklist" I have data in the following format:
Now what is the best way to set already selected children while loading v-Treeview? Thank You.
When the vue is created, the data hasn't been filled into the controllers and neither the page is rendered.
You can consider setting the selected items in the mounted
I have been working on a similar issue for hours and finally figured out how to get it work.
First of all, v-treeview needs a separate array of ids to keep the track of selected items.
you should bind it to the value property.
Second, the timing you change the value property is critical. v-model would not load the initial values so you have to update the values after you render the page. In your code above, you set the selectedItemList in created(). But it is executed before the page is rendered. You should put it into mounted() instead.
I don't think you can achieve this "out of the box".
I recommend using the "label" slot to add your own v-checkbox and bind the v-model to the selected property on your check list item.
Something like:
<v-treeview :items="checklist">
<template v-slot:label="props">
<div class="treeCheckBox">
<v-checkbox class="treeCheckBox"
v-model="props.item.selected"
:label="props.item.name">
</v-checkbox>
</div>
</template>
</v-treeview>
Then all you need to do is ensure the "selected" property is set appropriately against the check list items when the data is bound to the tree view.
For more info on the using the named slot, see https://vuetifyjs.com/en/components/treeview and https://v2.vuejs.org/v2/guide/components-slots.html
In version 1.5x of veutify you may encounter spacing issues. I was able to fix this by applying the following styles to my check box and outer div:
.treeCheckBox{
margin-top: 0px;
max-height: 30px;
}
I can't find a way to clear the select field in method "afterselection" which is invoked after selecting an item:
template:
<v-select
:items="adrlist"
#input="afterselection"
></v-select>
data in select:
const addressList = [{
"text":"Street 523, 2533",
"value":[1723455.7054408004,5923451.382843224]},
{"text":"Lala 3, 3455",
"value":[1723455.7054408004,5923451.382843224],
}]
vue-code:
new Vue({
el: '#app',
data () {
return {
adrlist: addressList,
}
},
methods:{
afterselection(item){
console.log(item);
//here I want to clear the select
},
},
})
Here's a code pen with this example:
codepen example
I've tried to set the v-model to null, but this is not working.
I have researched and tried for several days now, and I really can't find a solution :-/
Just for reference, you can clear a select field in vuetify with
this.$nextTick(() => {
this.selected = null
})
the important thing is the "nextTick"! otherwise it wont be rendered...
see this codepen provided by a vuetify-dev:
working codepen
I faced with the same issues. I have several v-select components in card text block and clear btn. When i click on clear i run clear func and clear all v-select items by refs.
template:
<v-card>
<v-card-title>Filters</v-card-title>
<v-card-text v-if="selectFilters.length">
<v-select
:ref="filter.id"
v-for="filter in selectFilters"
:items="filter.items"
:key="filter.id"
:label="filter.alias"
multiple
return-object
clearable
#input="selectChangeHandler($event, filter.id)"
></v-select>
</v-card-text>
<v-card-actions>
<v-btn color="primary" #click="clear">Clear</v-btn>
</v-card-actions>
</v-card>
script:
methods: {
...
clear: function() {
Object.values(this.$refs).forEach(ref => {
const vueSelect = ref[0];
vueSelect.internalValue = [];
});
},
}
you can achieve this by adding ref to the component
<v-select
ref="adrlistRef"
:items="adrlist"
#input="afterselection"
></v-select>
then use the reset method of v-select component whenever you want!
afterselection(item) {
if (item) {
console.log(item);
this.$refs['adrlistRef'].reset();
}
}
Looks like you need to bind to the select a v-model that is a computed property. Then it would be possible to change that value with the #input event.
I´m using the http://qtip2.com/ tooltips. I want to use a hidden element, for that i´m using this code:
<script type="text/javascript">
// <![CDATA[
// Grab all elements with the class "hasTooltip"
$('.hasTooltip').each(function() { // Notice the .each() loop, discussed below
$(this).qtip({
content: {
text: $(this).next('div') // Use the "div" element next to this for the content
}
});
});
// ]]>
And under this code:
<div class="hasTooltip">Hover me to see a tooltip</div>
<div class="hidden">
<!-- This class should hide the element, change it if needed -->
<p><strong>Complex HTML</strong> for your tooltip <em>here</em>!</p>
</div>
If you hover over the "Hover me to see a tooltip", no tooltip is shown? No idea, why?
events: {
render: (event, api) ->
show: (event, api) ->
$('.qtip:visible').qtip('hide')
elements = $(api.get('content.text')).removeClass('hidden')
api.set('content.text', elements)
,
hide: (event, api) ->
}
I think its a bug in Qtip2, i had to manually remove the class