user10753862
user10753862

Reputation:

receiving data from parent component vue.js: prop being mutated,

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

Answers (3)

Bill Souvas
Bill Souvas

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

imste
imste

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

Sean Reyes
Sean Reyes

Reputation: 1643

FIX FOR CLONED[i].apply

Vue 2 - Uncaught TypeError: cloned[i].apply is not a function at HTMLInputElement.invoker (vue.esm.js?65d7:1810) error

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

Related Questions