2
votes

I have a setting option , it will update from Parent Component. I am saving those setting data on localStorage and these three Child Component are using setting data.

<P>
  <c1> </c1>
  <c2> </c2>
  <c3> </c3>
</P>

I want like a way that when I will update my setting data the three component will refresh or update to get the new value. Like, I will press a button on Parent component and Three Child will be updated.

------------------------ UPDATED ------------------------------

TEMPLATE PART:

<template>
  <div class="main-content">
   <div class="main">

<!-- COMPONENT -->
<div class="row">
   <div class="padpad">
      <div class="col-md-6">
         <app-colma></app-colma>
      </div>
      <div class="col-md-3">
         <app-colmb></app-colmb>
      </div>
 
   </div>
</div>

<!-- SAVE BUTTON -->

          <button type="submit" class="btn btn-success" data-dismiss="modal" aria-label="Close" v-on:click="onSubmit()"><span>Save</span></button>
          
          
              
<!-- DATA FORM ( SELECT, OPTION) -->
               <div class="container modal-body">

                  <div class="col-xs-12 col-md-3">
                     <h4>Sortierung</h4>

                     <div class="radio">
                       <label><input value="theropeut" type="radio" name="filterop">Theropeut</label>
                     </div>
                     <div class="radio">
                       <label><input value="ausl_perf" type="radio" name="filterop">Ausl Perf</label>
                     </div>
                     <div class="radio">
                       <label><input value="ausl_bud" type="radio" name="filterop">Ausl Bud</label>
                     </div>
                     <div class="radio">
                       <label><input value="umsatz" type="radio" name="filterop">Umsatz</label>
                     </div>

                     <div class="order-select">
                        <select id="orderid" class="form-control">
                           <option value="ascending">Ascending</option>
                           <option value="descending">Descending</option>
                        </select>
                     </div>
                  </div>
   </div>
</div>
</template>

SCRIPT CODE:

<script>
import ColmA from './ColmA.vue';
import ColmB from './ColmB.vue';
import ColmTotal from './ColmTotal.vue';
export default {
  components: {
    'app-colma': ColmA,
    'app-colmb': ColmB,
    'app-colmtotal': ColmTotal
  },
	name: 'main-content',
	data() {
		return {
			users: [],
      filtr:'',
			order:''
		}
	},
	methods: {
    onSubmit: function(){
      // console.log("onsubmit");

      //filter
      var filterop = document.getElementsByName('filterop');

      for (var i = 0, length = filterop.length; i < length; i++) {
          if (filterop[i].checked) {
              // do whatever you want with the checked radio
              // alert(filterop[i].value);
              this.filtr = filterop[i].value;
              // only one radio can be logically checked, don't check the rest
              break;
          }
      }
      //order
      var e = document.getElementById("orderid");
      this.order = e.options[e.selectedIndex].value;

      var homesetting = {
          filter: this.filtr,
          order:this.order,
      };



      if (localStorage.getItem('homesetting') === null) {
        var  homesettings = [];

        // homesettings.push(homesetting);
        localStorage.setItem('homesetting', JSON.stringify(homesetting));
      } else {
        localStorage.removeItem('homesetting');
        localStorage.setItem('homesetting', JSON.stringify(homesetting));

      };
    }

	},

	created: function () {
		this.fetchData();
	}

}

</script>

COMPONENT CODE:

<script>
export default {
  name: 'colma',
  data () {
    return {
      title: 'A Area',
      colmAdata:[]
    }
  },
  methods: {
    fetchData: function () {
      var self = this;
      var homeObject = JSON.parse(localStorage.getItem('homesetting'));

      // console.log('retrievedObject: ', retrievedObject.filter);
      var filter= homeObject.filter;
      var order= homeObject.order;

      // HERE I NEED MY TWO UPDATED VARIABLES
      var a = 'http://localhost:3000/'+'_'+filter+'_'+order;
      console.log('A',a);


      $.get(apiURL, function (data) {
        self.colmAdata = data;
        // self.$store.state.storeGdata = ' store data from content';
        // console.log(data.people[0].name);

      });

    }

  },
	created: function () {
		this.fetchData();
	}
}
</script>
2
What have you tried? Where have you researched? - Script47

2 Answers

2
votes

One way around this is to emit a custom event from the child component (if the change originates from the child), and then capture/listen this event in the parent, which invokes a method. This method can then be used to invoke child methods that will update the value.

The real question is, why do you need to do this? Assuming that the parent component is the source of truth (i.e. passing data as props to the child components), then all you need is simply to watch for changes in these props, or use computed props to fetch updated values. There is no need to use events to invoke methods at all.

Basically, your modus operandi can be:

  1. Pass the parent values (stored in the parent data) as props to child components. The child components will reactively update their inherited properties.

  2. The parent's settings can also be stored to localStorage at the same time. This can be done by simply keeping a lookout for changes in parent data using watch. In this case, you can simply read from localStorage again when the parent is remounted (such as when the page is reloaded)—using the mounted lifecycle hook. These changes will, again, be propagated to child components as per point #1.

A proof-of-concept example (for the localStorage feature to work, please check this fiddle since code snippets are sandboxed):

Vue.component('child-component-a', {
  template: '<div><h2>Child component A</h2><p>I multiply inherited parent value by 2: <strong>{{ computedNumber }}</strong></p></div>',
  props: {
    number: {
      type: Number
    }
  },
  computed: {
    computedNumber() {
      return this.number * 2;
    }
  }
});

Vue.component('child-component-b', {
  template: '<div><h2>Child component B</h2><p>I divide inherited parent value by 16: <strong>{{ computedNumber }}</strong></p></div>',
  props: {
    number: {
      type: Number
    }
  },
  computed: {
    computedNumber() {
      return this.number / 16;
    }
  }
});

var app = new Vue({
  el: '#app',
  data: {
    parentNumber: 1024
  },
  watch: {
    parentNumber() {
      // Store parent number in localStorage when updated
      // *NOTE: Disabled in this code snippet since it is sandboxed
      // localStorage.setItem('parentNumber', this.parentNumber);
    }
  },
  mounted() {
    // Overwrite parent data if localStorage is found
    // *NOTE: Disabled in this code snippet since it is sandboxed
    // if (localStorage.getItem('parentNumber') !== null) {
    //   this.parentNumber = localStorage.getItem('parentNumber');
    // }
  }
});
html {
  font-family: Arial, sans-serif;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>
<div id="app">
  <div>
    <h1>Parent component</h1>
    <p>I have a value of <strong>{{ parentNumber }}</strong>.</p>
    <p>But wait, you can change my number!</p>
    <input v-model="parentNumber" type="number" />
  </div>
  <child-component-a v-bind:number="parentNumber"></child-component-a>
  <child-component-b v-bind:number="parentNumber"></child-component-b>
</div>
2
votes

If you use Vue.JS you should really just use Vue.JS - The parent should have a model which contains your settings as reactive data. Then you pass this property to your components as properties and the component just defines a watcher on the property.

var localStore = { reason: 'Fake, because no localStorage in Sandbox' };

Vue.component('rows', {
  props: ["order"],
  data: function(){ return { values: [] } },
  template: `<ul><li v-for="v in values">{{v}}</li></ul>`,
  created: function() { this.fetchValues() },
  watch: { order: function() { this.fetchValues() } },
  methods: { fetchValues: function() {
    /* Placeholder for an ajax-call with order as a parameter */
    this.values = ( this.order == 'ascending' ) ? [1,2,3] : [3,2,1]
  } }
})

new Vue({
  el: '#main',
  data: { order: 'ascending' },
  created: function() {
    if ( localStore.order ) {
      this.order = localStore.order;
    }
  },
  watch: { order: function() {
    /* Save any change on order in the local storage */
    localStore.order = this.order;
  } }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.js"></script>

<div id="main">
  <select v-model="order">
    <option value="ascending">Sort Ascending</option>
    <option value="descending">Sort Descending</option>
  </select>

  <rows :order="order"></rows>
</div>