I cannot find any examples using composition api for this and could use some direction. I have a q-select which passes options as a prop using a axios request. The data is in this form:
[{description: "Apple Inc.", displaySymbol: "AAPL"}, {description: "Microsoft", displaySymbol: "MSFT"}]
I have about 20000 records in this JSON response. I am able to display it all in a v-select using:
<q-select
filled
v-model="addStockSymbol"
use-input
input-debounce="0"
label="Add New Stock Symbol"
:options="stockTickers"
option-label="description"
option-value="displaySymbol"
@blur="addPosition"
@filter="filterFn"
behavior="menu"
>
<template v-slot:no-option>
<q-item>
<q-item-section >
No results
</q-item-section>
</q-item>
</template>
</q-select>
My issue is I do not know how to setup the filter and update function so I can search this. So far I have the code below but the examples on quasar do not use any arrays with objects but rather simple arrays. So I am wondering how do I approach this?
<script>
import {watch, ref, defineComponent,onMounted} from 'vue'
import {usePortfolioStore} from '../stores/portfolio-store'
import {storeToRefs} from 'pinia'
import {finnhubAPI} from 'boot/axios'
export default defineComponent({
name: 'UploadPositions',
components: {
},
setup () {
//v-models
const addStockSymbol = ref('')
const addShareCount = ref('')
const stockTickers = ref([])
const loadData = () => {
finnhubAPI.get('/api/v1/stock/symbol?exchange=US&token=tedkfjdkfdfd')
.then((response) => {
stockTickers.value = response.data
})
.catch(() => {
console.log('API request failed')
})
}
const filterFn = (val, update) => {
if (val === '') {
update(() => {
stockTickers.value =
})
return
}
}
update(() => {
const needle = val.toLowerCase()
this.options = stringOptions.filter(v => v.toLowerCase().indexOf(needle) > -1)
})
//add on mount API request
onMounted(() => {
loadData()
})
return {
addStockSymbol, addShareCount, portfolio, addPosition, deletePosition,
loadData, stockTickers, modifyTickerData, filterFn, update
}
}
})
</script>
CodePudding user response:
Basically you need to store a complete copy of the response data and keep that around, untouched, so that each time the filter function is called you can filter off of that, looking within its objects for the label
prop.
When setting up refs:
//v-models
const addStockSymbol = ref('')
const addShareCount = ref('')
const stockTickers = ref([])
const allResponseData= ref([]) // <-- add this one
Then your loadData function:
const loadData = () => {
finnhubAPI.get('/api/v1/stock/symbol?exchange=US&token=cc8ffgiad3iciiq4brf0')
.then((response) => {
const responseData = response.data.map((item) => ({label: item.description, value: item.displaySymbol}));
allResponseData.value = [...responseData];
stockTickers.value = [...responseData];
})
.catch(() => {
console.log('API request failed')
})
}
Then in your filter function:
const filterFn = (val, update, abort) => {
update(() => {
const needle = val.toLowerCase()
stockTickers.value = allResponseData.value.filter(option => {
return option.label.toLowerCase().indexOf(needle) > -1
})
})
}
See it in action:
const { ref } = Vue
const stringOptions = [
{label: 'Google', value: "goog"}, {label:'Facebook',value:'fb'}, {label:'Twitter', value: "twit"},{label: 'Apple', value: 'App'}]
const app = Vue.createApp({
setup () {
const options = ref(stringOptions)
return {
model: ref(null),
options,
filterFn (val, update, abort) {
update(() => {
const needle = val.toLowerCase()
options.value = stringOptions.filter(option => {
return option.label.toLowerCase().indexOf(needle) > -1
})
})
}
}
}
})
app.use(Quasar, { config: {} })
app.mount('#q-app')
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material Icons" rel="stylesheet"/>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/quasar.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/quasar.umd.prod.js"></script>
<!--
Forked from:
https://quasar.dev/vue-components/select#example--basic-filtering
-->
<div id="q-app" style="min-height: 100vh;">
<div >
<div >
<q-select
filled
v-model="model"
use-input
hide-selected
fill-input
input-debounce="0"
:options="options"
@filter="filterFn"
hint="Basic filtering"
style="width: 250px; padding-bottom: 32px"
>
<template v-slot:no-option>
<q-item>
<q-item-section >
No results
</q-item-section>
</q-item>
</template>
</q-select>
</div>
</div>
</div>