Props and computed


#1

im trying to show a side bar for filters
in my parent component i pass a prop on button click

 <filters class="sidebar-filters" v-if="filters.collections.length" :filters="filters" :showFiltersDiv="showFiltersDiv"/>

on child component i do this

<div id="filtersDiv" class="mb-4" :class="{'openfilters':open}">
    <a id="btnClose" href="javascript:void(0)" class="hidebtn" @click="hideFilters" >&times;</a>
   ....
</div>


 data(){
    return {
      open:this.showFiltersDiv
    }
  }, 
  props:{
      filters:{
          type:Object,
          required:true
      },
      showFiltersDiv:{
        type:Boolean,
        required:true
      }
  },
  methods:{
      hideFilters(){
        this.open=false;
    }
  },

it not works: nothign happen

please could help …im goin crazy beacuse if i use ‘showFiltersDiv’ i recive a warning from vue to not use a prop directly…


#2

Hi,
I have a question, Is there any reason to use open instead showFiltersDiv?
Could you post the error please?
Maybe using like this:

props: ['filters', 'showFiltersDiv']

Regards


#3

hi
tks for help
the error says

Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value

if i use the showFiltersDiv all works great but i get the warning above

im confused


#4

Ok, then you should use something like this:

props: ['filters', 'showFiltersDiv'],
  computed: {
    open: function() {
    return this.showFiltersDiv;
  }
},
methods:{
  hideFilters() {
    this.showFiltersDiv = !this.showFiltersDiv;
  }
}

It’s a good practice to provide a sample code in order to have a better perspective of the issue.
I did an example for what I can understand is doing your code here.
Please, review it and tell us how is going.

Regards


#5

is still mutating the prop on that component directly and will still show the warning message he is receiving. It is not advised to mutate props like this directly.


#6

@bolerodan You are totally right… I have forgot that method.

Here is the correct code:

 props: ['showFiltersDiv', 'filters'],
 data: function() {
   return {
     open: ''
   };
 },
 methods: {
	hideFilters() {
		this.open = !this.open;
	},
 },
 created: function() {
    this.open = this.showFiltersDiv;
 }

Here I did a copy of the variable when the component is created. So, all the changes will be kept as local.
Hope this helps.


#7

it not works: not open!
If manually add class ‘openfilters’ the hidefilters method works
No errors no warning :frowning:


#8

Weird, this works on the example that I posted. Could you give us the example?


#9

in the child i have this

<template>
  <div id="filtersDiv" class="mb-4" :class="{'openfilters':open}">
    <a id="btnClose" href="javascript:void(0)" class="hidebtn" @click="hideFilters" >&times;</a>
    ...  </div>
</template>

<script>
export default {
  name:"filters",
  data(){
    return {
      open:''
    }
  }, 
  props:{
      filters:{
          type:Object,
          required:true
      },
      showFiltersDiv:{
        type:Boolean,
        required:true
      }
  },
  
  methods:{
    
      hideFilters(){
       this.open = !this.open;    
    }
  },
  created(){
     this.open = this.showFiltersDiv;
  }
  /*
  mounted(){
    let filtersDiv = document.getElementById('filtersDiv');
    let btnClose = document.getElementById('btnClose');
 
    btnClose.addEventListener('click',hide);
    function hide(){
      filtersDiv.classList.remove("openfilters");
     }
  } 
  */ 
}
</script>

in parent component

 <filters class="sidebar-filters" v-if="filters.collections.length" :filters="filters" :showFiltersDiv="showFiltersDiv"/>

#10

I did found the issue.

<filters class="sidebar-filters" v-if="filters.length" :filters="filters" :show-filters-div="showFiltersDiv"/>

As you can see, the attribute must be described as :show-filters-div, if this is not set like that, the value become undefined.

So, you can change [:showFiltersDiv=“showFiltersDiv”] to [:show-filters-div=“showFiltersDiv”] in the parent component.

See my updated code here.

Happy coding!


#11

it seems not work
thks so much for help
but now my eyes are burning :hugs:
tommorrow i retry
bye


#12

i have try but only the close method works


#13

I do not understand… I supposed that this was the issue… that your method hideFilters did not work properly.
Sorry, but I don’t get your point.
Or what was the issue, then?


#14

The issue is that work great using directly the props showfilterdiv but get warning from vue compiler

So try to follow the warning and use a data or computed prop but i not have success


#15

But, are you sure that you followed the example code that I posted?

  props: ['filters', 'showFiltersDiv'],
  data: function() {
    return {
        open: JSON.parse(JSON.stringify(this.showFiltersDiv))
    };
  },
  methods: {
	hideFilters: function() {
		this.open = !this.open;
	}
  }

It seems to be working O.K.


#16

hi
now i see the ‘open’ in data change correctly but the class ‘openfilters’ is not removed
Seems we are so close to solution

<template>
  <div id="filtersDiv" :class="{'mb-4':true,'openfilters':open}" > {{open}}
    <a id="btnClose" href="javascript:void(0)" @click="hideFilters" class="hidebtn">&times;</a>
   ...
  </div>
</template>

<script>

export default {
  name:"filters",
  data(){
    return {
      open: JSON.parse(JSON.stringify(this.showFiltersDiv))
    }
  }, 
  props:{
      filters:{
          type:Object,
          required:true
      },
      showFiltersDiv:{
        type:Boolean
      }
  },
  methods:{
     
     hideFilters() {
      this.open = !this.open;
    }
  }
}
</script>


</style>


<template>
  <div class="container">
    <filters :class="{'sidebar-filters':true,'openfilters':showFiltersDiv}"  v-if="filters.collections.length" 
    :filters="filters" :numberProducts="sortedProducts.length" :showFiltersDiv="showFiltersDiv"/>

  </div>
</template>

<script>

export default {
  name: "catalogue",
  data() {
    return {
      showFiltersDiv: false
    };
  },
  methods: {
    showFilters() {
      this.showFiltersDiv = true;
    }
  
};
</script>

<style lang="scss">

.openfilters {
  width: 50%!important;
  box-shadow: 10px 10px 5px 0px rgba(235,232,235,1);
}
</style>


#17

im sure you are righe and for me the question is solved
here a confirm

but it cant work :frowning:
i go on with project because i cant stop there
so bye
and tks a lot


#18

at the end I solved with

closeFilters(){
        this.$emit("close");
     }