Reputation: 11
I am trying to add two way binding to custom admin component in shopware.
<range-slider v-model="vuejsvar"></range-slider>
The problem is the v-model variable vuejsvar is not getting updated, as I change the value of the input range element specified below.
The template twig file.
<% range_slider %>
<template>
<div class="range-slider">
<label v-if="hasLabelSlot">
<slot name="label">
</slot>
</label>
<input type="range" min="0" max="100" step="1" :value="currentValue" :name="name" v-bind="$attrs" @change="onChange" v-on="additionalListeners">
<div class='range-slider__progress'>{{ currentValue }}</div>
</div>
</template>
<% endblock %>
The issue in the below code.
watch: {
value(value) {
this.currentValue = value;
}
},
This code updates the value for vuejsvar as [Object event] as i move the range slider. I event tried the following.
watch: {
value(event) {
this.currentValue = event.target.value;
}
},
Still updates vuejsvar variable as [Object event].
Full code
The index.js file
const { Component, Mixin } = Shopware;
const { Criteria } = Shopware.Data;
import template from './range-slider.html.twig'; // template which will show data
Shopware.Component.register('range-slider', {
template: template,
inheritAttrs: false,
props: {
value: {
required: true,
},
name: {
type: String,
required:true,
default:''
}
},
data() {
return {
currentValue: this.value,
};
},
computed: {
hasLabelSlot() {
return (this.$slots['label']);
},
additionalListeners() {
const additionalListeners = Object.assign({}, this.$listeners);
delete additionalListeners.change;
return additionalListeners;
},
},
watch: {
value(value) {
this.currentValue = value;
}
},
methods: {
onChange(event) {
this.$emit('change', event.target.value );
},
}
});
I based my code of https://github.com/shopware/administration/tree/trunk/Resources/app/administration/src/app/component/form/sw-text-field
Upvotes: 1
Views: 419
Reputation: 5183
If you want to use v-model
then you have to fire the input
event.
Check the Vue Docs: Using v-model on Components
<input v-model="searchText">
Is the same as:
<input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value">
So, you have to use the input
event or catch the change
event yourself.
Like this:
<range-slider :value="vuejsvar" @change="onChange"></range-slider>
and
methods: {
onChange(event) {
this.vuejsvar = event;
}
}
But than you don't need the v-model
at all.
Check the playground:
var RangeSlider = {
template: '#range-slider',
props: {
value: {
required: true,
},
name: {
type: String,
required:true,
default:''
}
},
data() {
return {
currentValue: this.value,
};
},
watch: {
value(value) {
this.currentValue = value;
}
},
methods: {
onChange(event) {
this.$emit('input', event.target.value );
},
}
};
var Main = {
el: '#app',
components: {
'range-slider': RangeSlider,
},
data() {
return {
vuejsvar: 50
}
},
methods: {
onChange(event) {
this.vuejsvar = event;
},
}
};
Vue.component('range-slider', RangeSlider)
const vm = new Vue(Main);
<html>
<head>
</head>
<body>
<div id="app">
vuejsvar: {{vuejsvar}}<br />
range-slider: <range-slider v-model="vuejsvar" name="slider"></range-slider>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<script type="text/x-template" id="range-slider">
<div class="range-slider">
<label>
<slot name="label">
</slot>
</label>
<input type="range" min="0" max="100" step="1" :value="currentValue" :name="name" v-bind="$attrs" @change="onChange" >
<div class='range-slider__progress'>{{ currentValue }}</div>
</div></script>
</body>
</html>
Upvotes: 0