Deselect v-list-item when changing its value - vue.js

I have a v-list-item-group with some v-list-item's inside with an associated value. The problem is that when I change the value of the selected v-list-item it doesn't react. I want it to be selected only when the new value matches the v-list-item-group's model and be unselected otherwise. What is the best way to achieve such a behaviour?
Example. When you edit the list item value, for example, by changing the lower left field from "Bluetooth" to "Bluetooth1", I want the list item to get deselected automatically because its value isn't longer matching v-list-item-group's model ("Bluetooth1" != "Bluetooth"). And when you change it back to "Bluetooth" I want it to get selected again.
The one on the right modifies the v-list-item-group's model and this works as expected.
My actual use case is rendering lists of thousands of elements quickly without rendering them all. To achieve it I use a recycle-scroller component inside my v-list-item-group to manage its items. It creates a few dozens of v-list-items and as user scrolls it reuses them by moving them around and replacing their value, icon and text with corresponding data from my array. The problem is that when user selects some list item then scrolls the list, the selected item gets reused. Despite the fact that it now has a different value, text and icon it still looks as selected. So they see it as if some different item was selected.

I hope this works for you:
<v-list-item-group v-model="model" :color="color">
// other html
Then add a computed property:
computed: {
color(){
if (this.model == this.items[1].text) {
return 'indigo'
} else {
return 'black'
}
}
}

Related

How to programmatically expand all rows in a v-data-table component (Vuetify version 1.5)

v-data-table component has a propery "expanded" that allows to show some additional info for each row.
It works fine and I need to expand all the rows immediately when a page is loaded.
Is there a way to do that?
It is used version 1.5 of Vuetify Framework.
https://v15.vuetifyjs.com/en/components/data-tables
This is fairly easy in the new Version of Vuetify, you just use the property expanded which holds an Array of the items that are currently expanded.
<v-data-table
id="issues-table"
:value="selectedIssues"
:expanded="expandedIssues"
:items="issues"
>
<v-switch #change="(v) => expandAllIssues(items, v)" />
expandAllIssues (items, status) {
if (status) {
this.expandedIssues = items
} else {
this.expandedIssues = []
}
}
In V1.5.xx of Vuetify you don't have that luxury, but when I took a look, Vuetify works with a similar system under the hood. Firstly you should set the expand prop on the table to true, so it can expand multiple rows.
You can define a reference on your data table and then access it via this.$refs.myDataTableRef. You then realise that they store the expanded rows in an Object called expanded. You can set the rows either true by the id/name of the row in this object or you simply set the whole row objects in the vuetify expanded object to true.
I have pasted the Codepen example of their old data table and made a simple expand all button, that you can obviously change to your desires, but it should make the concept clear.
Codepen example

Dynamically updating v-combobox items list

Is it possible somehow to update Vuetify v-combobox items as the user is typing? I want to change the list of available items depending on what the users started typing, to create an address input with suggestions from a geolocation API.
This is what I tried: #update:search-input='fetchAddresses'
And in fetchAddresses: this.items = newListOfItems
However, while #update:search-input fires as expected, the combobox list will only be updated after losing focus. Can I somehow trigger it to be updated? (This may very well be an X/Y problem, so any hints about other approaches are welcome)
My current, ugly, hack is to force the whole combobox component to re-render with the current value set, and then refocus on it. (There is an activateMenu() method on the combobox that I could use to make sure the list reopened:
this.$nextTick(() => {
if (this.$refs.addressCombobox) {
this.$refs.addressCombobox.focus()
this.$refs.addressCombobox.activateMenu()
}
})
I'm using Vue 2.
In my case no-filter solved this problem
<v-combobox no-filter ... >

Vue js event not fired for item filtered out of list

I have a list of items. Each item has a "complete" flag. If this flag is true, the item shows in view A. If it is false, it shows in view B. The items are retrieved via an API request, with a client-side filter applied through a computed method on the base dataset. So for view A it will return items with complete=true, for view B, it will return items with complete=false.
The complete flag is editable (via a checkbox). I have a watcher function on the complete field that results in a PATCH being made to the item to toggle the complete field on the server.
Here's the issue. Since the vue app is filtering items based on the complete flag, any time that field changes, the item is removed from the view, so the watcher never gets triggered and the PATCH is never made.
It makes sense that the item's removal would cause the filter function to be re-run, however it seems odd that the watcher is killed before it can run.
So my question is, how do I achieve this - a list of filtered objects where the filter criteria can be changed, and have that change recognized via a watcher or similar?
You're probably better off using an #input event on the checkbox, and tying that to the api call:
<input type="checkbox" #input="onCheckChange">
...
methods: {
onCheckChange() {
// Perform API call here.
}
}

Titanium get current view on scrollableView and add an item

I have a scrollableView with several views inside and I'd like to add item to some of these view if they meet a certain criteria, like if they have data attached or not. Also I'm using Alloy, here's my markup
<ScrollableView id="scrollableView">
<View id="view" class='coolView'></View>
...
</ScrollableView>
To know if there are data attached I check the currentPage attribute like so:
function updateCurrentView(e) {
currentView = e.currentPage;
}
But I have no idea how to add an item to the current View.
Edit: To add some clarification, I have a label which when clicked allow me to choose two currencies, when chosen these currency pairs are saved in the database and should be displayed instead of the label. So my guess was to check whether the current view has currency pair saved.
There are 2 things to take care of here:
1.Whenever a currency is selected,immediately label on that particular view will change.
2.Whenever the scrollableView is loaded,it must always refer to the database if a currency is selected.
First one can be done as:
1.Get the instance of scrollableView using the getView method of alloy controller.Pass the id of the scrollableView to it.Lets call it myScrollableView.Refer this for more info.
http://docs.appcelerator.com/titanium/latest/#!/api/Alloy.Controller
2.Use var currentView=myScrollableView.getCurrentPage() to the get the current page which will be a number.
3.Now use the scrollableView instance to get all the views.
var viewArray=myScrollableView.getViews();
4.viewArray[currentView] will give you the view of current page.After you have got the view you can change the desired label using:
viewArray[currentView].children[positionOfTheView]
The "positionOfTheView" can be obtained by printing the viewArray[i].children array using Ti.API.info.
Second thing can be accomplished as follows:
1.Get the instance of scrollableView using the getView method of alloy controller.Pass the id of the scrollableView to it.Lets call it myScrollableView.Refer this for more info.
http://docs.appcelerator.com/titanium/latest/#!/api/Alloy.Controller
2.Now use the scrollableView instance to get all the views.
var viewArray=myScrollableView.getViews();
3.This is a JavaScript array of all the views in the scrollableView. Now iterate through this array and according to the data in the database,change the concerned view using:
viewArray[i].children[positionOfTheView]
The "positionOfTheView" can be obtained by printing the viewArray[i].children array using Ti.API.info.

Filter using checkboxes - Logic Issue

I have a grouped Checkbox, and it has 4 checkboxes in it.
When the user selects a checkbox I need to filter a data store based on the value of the text box. When i select 2 textboxes, I get the output of ["Albert","Francis"], and when I select only the 1st textbox I get ["Albert"] and so forth.
Now, i need to know how to filter this ?
onCheckBoxGroupChange : function (field,newValue,oldValue,options) {
var chkv=newValue.chb;
console.log (chkv);
var st= Ext.getStore('People');
st.on('load', function() {
st.filter({
filterFn: function(rec) {
return rec.get('name') == chkv;
The problem I am having is, when I select both the CheckBoxes, chkv becomes ["Albert","Francis"] (Like an array), therefore I am unable to return the value since rec.get('name') == chkv; doesn't look for an array.
Can someone help me?
what about:
filterFn: function(rec) {
return Ext.Array.contains(chkv, rec.get('name'));
}
I want to make sure you know that you do not have to reload the store if you want to filter it. It looks like that is what you are doing in the snippet you provided above.
There are other problems actually, what your onCheckBoxGroupChange handler will actually do (if you leave it the way you have it above), is the following:
Every time a user clicks a checkbox it will first reload the store from the server, and then add the selected filter to the store's filters and then filter the store by the filters it has saved.
E.g.:
User clicks "Albert" checkbox
Store reloads
Store adds `["Albert"]` filter function
Store performs filtering with `["Albert"]` filter function
User clicks "Francis" checkbox
Store reloads
Store adds `["Albert", "Francis"]` filter function
Store performs filtering with `["Albert"]` filter function
Store performs filtering with `["Albert", "Francis"]` filter function
User unclicks "Albert" checkbox
Store reloads
Store adds `["Francis"]` filter function
Store performs filtering with `["Albert"]` filter function
Store performs filtering with `["Albert", "Francis"]` filter function
Store performs filtering with `["Francis"]` filter function
You would just progressively get more and more filters. Plus unnecessarily reloading the store many times. I don't think that is what you are going for.
You should review the docs on datastore filtering for more data on how to go about this.
Also, in your question you said that you had this problem when you selected two checkboxes because it returned an array. According to the text of your question you are also getting an array when you select one checkbox (["Albert"]). It only has one item in it but it is an array.
That is why my solution (which requires your chkv variable to be an array) would work.