Martyn Ball
Martyn Ball

Reputation: 4885

VueJS: Bind values to Component

Not sure how to explain this question, and I can't find an answer within the documentation.

Basically within my data I have got an array with 2 values, these represent the index of the day of the week. I want to make a range component where I can add some additional functionality, for example in my example this will be a range slider with 2 handles, I just haven't added the styles.

Vue.component('range', {
  props: [ 'step', 'min', 'max', 'value' ],
  created() {
    this.minValue = this.value[0];
    this.maxValue = this.value[1];
  },
  data: function() {
    return {
      minValue: 0,
      maxValue: 0
    }
  },
  template: `<div>
    <input type="range" name="points" :min="this.min" :max="this.max" :step="this.step" :value="minValue">
    <input type="range" name="points" :min="this.min" :max="this.max" :step="this.step" :value="maxValue">
  </div>`
});

window.app = new Vue({
  el: '#app',
  data: {
    'weekdays': [ 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday' ],
    'locations': [
      {
        'id': 1,
        'name': 'Test Place',
        'hours': [
          {
            'id': 1,
            'weekdays': [ 0, 4 ]
          },
          {
            'id': 2,
            'weekdays': [ 5, 5 ]
          },
          {
            'id': 3,
            'weekdays': [ 6, 6 ]
          }
        ]
      }
    ]
  }
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
  <div class="location" v-for="(location, index) in locations">
    <h3>{{ location.name }}: {{ location.id }}</h3>
    <div class="hours">
      <div v-for="(hour, index) in location.hours">
        <p>Hour ID: {{ hour.id }}</p>
        <range step="1" min="0" max="6" :value="hour.weekdays"></range>
      </div> 
    </div>
  </div>
</div>

I have created a minimal example above. Now, my question is, is there a way without emitting the data back to the parent, that I can use v-model to change the array based on my 2 sliders within my main component.

So, theoretical example:

<range step="1" min="0" max="6" :value="hour.weekdays" v-modal="hour.weekdays"></range>

Upvotes: 0

Views: 419

Answers (1)

Steven B.
Steven B.

Reputation: 9362

v-model is just syntatical sugar for

<some-component
    v-bind:value=""
    v-on:input="">
</some-component>

So you can accomplish using v-model on the component by adding watchers internal to the component and emitting an event with a value of the array.

Vue.component('range', {
  props: [ 'step', 'min', 'max', 'value' ],
  created() {
    this.minValue = this.value[0];
    this.maxValue = this.value[1];
  },
  data: function() {
    return {
      minValue: 0,
      maxValue: 0
    };
  },
  methods: {
    emitOut() {
    	this.$emit('input', [this.minValue, this.maxValue]);
    },
  },
  watch: {
    minValue(newVal) {
    	this.emitOut();
    },
    maxValue(newVal) {
    	this.emitOut();
    },
  },
  template: `<div>
    <input type="range" name="points" :min="this.min" :max="this.max" :step="this.step" v-model="minValue">
    <input type="range" name="points" :min="this.min" :max="this.max" :step="this.step" v-model="maxValue">
  </div>`
});

window.app = new Vue({
  el: '#app',
  data: {
    'weekdays': [ 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday' ],
    'locations': [
      {
        'id': 1,
        'name': 'Test Place',
        'hours': [
          {
            'id': 1,
            'weekdays': [ 0, 4 ]
          },
          {
            'id': 2,
            'weekdays': [ 5, 5 ]
          },
          {
            'id': 3,
            'weekdays': [ 6, 6 ]
          }
        ]
      }
    ]
  }
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
  <div class="location" v-for="(location, index) in locations">
    <h3>{{ location.name }}: {{ location.id }}</h3>
    <div class="hours">
      <div v-for="(hour, index) in location.hours">
        <p>Hour ID: {{ hour.id }}</p>
        First: {{ hour.weekdays[0] }}
        Second: {{ hour.weekdays[1] }}
        <range step="1" min="0" max="6" v-model="hour.weekdays"></range>
      </div> 
    </div>
  </div>
</div>

Upvotes: 1

Related Questions