Reputation: 436
I'm using Vue.js version 3. Here is my full code with dummy data and options API with filters and sorting, and everyting works very well
<template>
<h5>List of Products</h5>
<h3>Filter</h3>
<button v-on:click="resetOptions">Reset</button>
<button v-on:click="sorting">Sorting</button>
<button v-on:click="sorting2">Sorting2</button>
<select v-model="category">
<option value="Accessories">Accessories</option>
<option value="Laptop">Laptop</option>
<option value="Stationary">Stationary</option>
</select>
<div>
<input type="checkbox" name="test" id="test" v-model="city" value='Roma' />
<label for="test"> Roma</label>
<input type="checkbox" name="test2" id="test2" v-model.trim="city" value='Barselona' />
<label for="test2"> Barselona</label>
<input type="checkbox" name="test3" id="test3" v-model.trim="city" value='Milano' />
<label for="test3"> Milano</label>
</div>
<!-- <select v-model="city">
<option value="Barselona">Barselona</option>
<option value="Roma"> Roma </option>
<option value="Milano">Milano</option>
</select> -->
<input type="text" v-model="name" placeholder="Filter By Name"/>
<label for="vol">Price (between 0 and 1000):</label>
<input type="range" v-model.trim="range" min="0" max="1000" step="10"/>
<ul>
<li v-for="product in filterProducts" :key="product.name"> Product Name : {{product.name}} - Price : {{product.price}} ({{product.category}})
{{product.city}}
</li>
</ul>
</template>
<script>
import getPosts from '../composables/getPosts'
export default {
data: ()=> ( {
city:['Roma', 'Barselona', 'Milano'],
category: '',
name: '',
range: '10000',
products: [
{ name: "Keyboard", price: 44, category: 'Accessories', city:'Roma'},
{ name: "Mouse", price: 20, category: 'Accessories', city:'Barselona'},
{ name: "Monitor", price: 399, category: 'Accessories', city:'Roma'},
{ name: "Dell XPS", price: 599, category: 'Laptop', city:'Roma'},
{ name: "MacBook Pro", price: 899, category: 'Laptop', city:'Roma'},
{ name: "Pencil Box", price: 6, category: 'Stationary', city:'Barselona'},
{ name: "Pen", price: 2, category: 'Stationary', city:'Milano'},
{ name: "USB Cable", price: 7, category: 'Accessories', city:'Milano'},
{ name: "Eraser", price: 2, category: 'Stationary', city:'Roma'},
{ name: "Highlighter", price: 5, category: 'Stationary', city:'Roma'}
]
}),
computed: {
filterProducts: function(){
return
this.filterProductsByName(this.filterProductsByRange(this.filterProductsByCity(this.filterProductsByCateg
ory(this.products))))
},
},
methods: {
filterProductsByCategory: function(products){
return products.filter(product => !product.category.indexOf(this.category))
},
filterProductsByName: function(products) {
return products.filter(product =>
!product.name.toLowerCase().indexOf(this.name.toLowerCase()))
},
filterProductsByCity: function(products) {
return products.filter(product => this.city.indexOf(product.city) !== -1)
},
filterProductsByCity2: function(products) {
return products.filter(product => !product.city.indexOf(this.city))
},
filterProductsByRange: function(products){
return products.filter(product => (product.price >= 0 && product.price <= this.range) ? product : '')
},
sorting:function(){
this.products.sort((a,b)=>(a.price > b.price) ? 1 : -1)
},
sorting2:function(){
this.products.sort((a,b)=>(a.price < b.price) ? 1 : -1)
},
uniqueCheck(e){
this.city = [];
if (e.target.checked) {
this.city.push(e.target.value);
}
},
resetOptions:function(){
this.category='',
this.city='',
this.name='',
this.range='1000'
},
},
}
</script>
<style>
</style>
But I want to convert this to Composition API and I put dummy data in fake API. I made that API call and put it in the getProducts.js file. That file I imported on this page where I want to show that data. And that works fine. But I have a problem with converting functions from Options API to Composition API Here is my code
<template>
<div class='home'>
<h1>Third</h1>
<select v-model="category">
<option value="Accessories">Accessories</option>
<option value="Laptop">Laptop</option>
<option value="Stationary">Stationary</option>
</select>
<div>
<input type="checkbox" name="test" id="test" v-model="city" value='Roma' />
<label for="test"> Roma</label>
</div>
<div v-if="error"> {{error}} </div>
<div v-if="products.length">
<div v-for="product in filterProducts" :key='product.price'>
<h3>{{product.name }}</h3>
<h4>{{product.category}}</h4>
</div>
</div>
<div v-else> Loading...</div>
</div>
</template>
<script>
import { computed, ref} from 'vue'
import getProducts from '../composables/getProducts'
export default {
components: {} ,
setup(){
const category = ref('')
const city = ref('')
const{products,error,load} = getProducts()
load()
function filterProductsByCategory (products){
return products.filter(product => !product.category.indexOf(category.value))
}
function filterProductsByCity (products) {
return products.filter(product => city.value.indexOf(product.city) !== -1)
}
const filterProducts = computed (()=> {
return filterProductsByCity.value(filterProductsByCategory.value(products.value))**
})
return {products, error, category, city, filterProducts, filterProductsByCity, filterProductsByCategory}
}
}
</script>
<style>
</style>
This is a part of my filter functions, It's problem in functions I think. I changed everything that I needed to convert Options API to Composition API
So here is just a part of filter logic but if someone helps me with this I will convert all code easily
Upvotes: 14
Views: 9228
Reputation: 768
<script setup>
version for composition api code can be done as follows.
<script setup>
import DemoComponent from "./Demo.vue"
import { onMounted, ref, computed } from "vue";
const demoVar = ref(""); //data property of options api
const demoComputed = computed(()=>{
return {};
}); // computed property
//Methods can be declared in 2 ways
//1st
function demo(){
//logic
}
//2nd
const demoTwo = function(){};
//lifecycle hook
onMounted(() => {})
</script>
For more info on declaring methods and its uses please check Proper use of const for defining functions
We don't need to return const
and function
at end of the script, with script setup everything is directly accessible to the template even components
.
<script setup>
provides more readability and avoids unnecessary errors due to missed out declarations in return
. For more details script setup
Upvotes: 2
Reputation: 138196
data
Replace each data property with a ref
. We'll update their references within setup()
when converting methods
later.
Use onMounted
to call load()
upon mounting the component.
import { ref, onMounted } from 'vue'
import getProducts from '@/composables/getProducts'
export default {
setup() {
const { products, load } = getProducts()
const category = ref('')
const city = ref([])
const name = ref('')
const range = ref('10000')
onMounted(() => load()) // load products
return {
// properties that the template needs should be returned here
products,
category,
city,
name,
range,
}
}
}
methods
setup()
.ref
s, update their code references to unwrap the ref
(i.e., this.name
should be name.value
, etc.).export default {
setup() {
//...
const filterProductsByCategory = (products) => {
return category.value
? products.filter((product) => !product.category.indexOf(category.value))
: products
}
const filterProductsByName = (products) => {
return name.value
? products.filter((product) => !product.name.toLowerCase().indexOf(name.value.toLowerCase()))
: products
}
const filterProductsByCity = (products) => {
return city.value && city.value.length
? products.filter((product) => city.value.indexOf(product.city) !== -1)
: products
}
const filterProductsByRange = (products) => {
return range.value
? products.filter((product) => product.price >= 0 && product.price <= range.value)
: products
}
const sorting = () => products.value.sort((a, b) => (a.price > b.price ? 1 : -1))
const sorting2 = () => products.value.sort((a, b) => (a.price < b.price ? 1 : -1))
const uniqueCheck = (e) => {
city.value = []
if (e.target.checked) {
city.value.push(e.target.value)
}
}
const resetOptions = () => {
category.value = ''
city.value = ''
name.value = ''
range.value = '1000'
}
return {
//...
// methods that the template needs should be returned here
sorting,
sorting2,
uniqueCheck,
resetOptions,
}
}
}
computed
computed
to create a computed property, referencing the function instances and ref
s created above in setup()
.import { computed } from 'vue'
export default {
setup() {
//...
const filterProducts = computed(() => {
return filterProductsByName(
filterProductsByRange(
filterProductsByCity(filterProductsByCategory(products.value))
)
)
})
return {
//...
filterProducts,
}
}
}
Upvotes: 18