Reputation: 1751
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
class="grey-7"
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 class="text-grey">
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>
Upvotes: 2
Views: 8067
Reputation: 6552
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 class="q-pa-md">
<div class="q-gutter-md row">
<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 class="text-grey">
No results
</q-item-section>
</q-item>
</template>
</q-select>
</div>
</div>
</div>
Upvotes: 4