Reputation:
I have an error in the console that is saying:
Instead, use a data or computed property based on the prop's value. Prop being mutated: "sortType"
My root file contains an api and a filter function. I am sending that data to components. Everything was fine 'til I added some sorting in filterList().
This is how I am receiving the sortType
:
<div id="toprow">
// slider codes...
<select id="sortBox" v-model="sortData" v-on:change="filterList">
<option value="">sorting</option>
<option value="price">cheapest</option>
<option value="created_at">newest</option>
</select>
</div>
props:["filterList", "slider", "sliderX", "sortType"],
components: {
vueSlider,
},
data() {
return {
sortData: this.sortType
}
},
methods: {
filterList(newType){
this.$emit('update:type', newType)
}
}
Below, my root file...
<app-toprow v-on:update:type="sortType = $event" :filterList="filterList" :slider="slider" :sliderX="sliderX" :sortType="sortType"></app-toprow>
data(){
return {
api: [],
sortType:"",
}
},
mounted(){
axios.get("ajax").then(response => {
this.api = response.data
})
},
methods: {
},
computed: {
filterList: function () {
let filteredStates = this.api.filter((estate) => {
return (this.keyword.length === 0 || estate.address.includes(this.keyword)) &&
(this.rooms.length === 0 || this.rooms.includes(estate.rooms)) &&
(this.regions.length === 0 || this.regions.includes(estate.region))});
if(this.sortType == 'price') {
filteredStates = filteredStates.sort((prev, curr) => prev.price - curr.price);
}
if(this.sortType == 'created_at') {
filteredStates = filteredStates.sort((prev, curr) => Date.parse(curr.created_at) - Date.parse(prev.created_at));
}
return filteredStates;
},
}
}
Okay, am I doing something wrong when I receiving the sortType?
Upvotes: 1
Views: 294
Reputation: 46
You pass sortType
as a prop into the child component and simultaneously mutate it using the v-model
in select, thus receiving this error.
Your child component should be something like:
<div id="toprow">
// slider codes...
<select id="sortBox" v-model="selectedSort" v-on:change="filterList">
<option value="">sorting</option>
<option value="price">cheapest</option>
<option value="created_at">newest</option>
</select>
</div>
export default {
data() => ({
selectedSort: this.sortType
})
props:["filterList", "slider", "sliderX", "sortType"],
components: {
vueSlider,
},
methods: {
filterList(newType){
this.$emit('update:type', newType)
}
}
}
Now on the v-on:change=filterList
you should emit a custom event on the parent that notifies him that the sorting has changed.
And something like this on the parent:
<app-toprow v-on:update:type="sortType = $event" :filterList="filterList" :slider="slider" :sliderX="sliderX" :sortType="sortType"></app-toprow>
Relevant SO question: https://stackoverflow.com/a/51722100/7482509 Relevant docs: https://v2.vuejs.org/v2/guide/components-custom-events.html, https://v2.vuejs.org/v2/guide/components-props.html#One-Way-Data-Flow
Upvotes: 1
Reputation: 360
does the select option didn't has default value (the value is always sorting
on page load)? if yes you don't have to use v-model
if it has default value, try use :value
instead of v-model
, and use the props sortType
as the value.
also you can't use same name on filterList
, try using different variable for the function.
<div id="toprow">
// slider codes...
<select id="sortBox" :value="sortType" v-on:change="change">
<option value="">sorting</option>
<option value="price">cheapest</option>
<option value="created_at">newest</option>
</select>
</div>
on the change Function
export default {
methods: {
change(e){
this.$emit('update:type', e.target.value)
}
}
}
on your parent component
<app-toprow v-on:update:type="sortType = $event" :filterList="filterList" :slider="slider" :sliderX="sliderX" :sortType="sortType"></app-toprow>
Upvotes: 0
Reputation: 1643
FIX FOR CLONED[i].apply
basically you should just change the prop name filterList
to something else
NEW ANSWER
here's an update answer, prop filterList
is the same name as in method I do think that is conflict. also i do think that you don't need to send filterList
method from parent to children because you are already listening on if via update:type
methods: {
filterList(event){
// use the v-model reactive feature..
this.$emit('update:type', this.sortData)
// if you don't like this.sortData -> uncomment below
// this.$emit('update:type', event.target.value)
}
}
OLD
why don't you use mounted()
for initializing sortData: this.sortType
...
data() {
return {
sortData: null
}
},
mounted() {
this.sortData = this.sortType
}
P.S.
Just my theory... I could not explain clearly why this is happening but I do think that this is because vue is reactive and all data values should not have a value directly from prop. because if you think about it if it came from prop DIRECTLY therefor editing it should also edit the prop..
but I don't really know why it's doing that, better ask that another time.
Upvotes: 0