2

I have some components that look like this.

<template>
  <q-layout>
    <v-input v-model="something" />
  </q-layout>
</template>

<script>
import { QLayout } from 'quasar'
import { Input } from 'vedana'

export default {
  name: 'index',
  components: {
    QLayout,
    Input
  },
  data () {
    return {
      something: ''
    }
  }
}

this v-input component looks like this:

<template>
    <input
        :type="type ? type : 'text'"
        class="v-input"/>
</template>

<script>
export default {
    props: ['type'],
    name: 'v-input'
}
</script>

When I enter data into the input something does not bind to whatever is in the value of the input that is inside of v-input.

How do I achieve this?

3
  • 2
    You are importing Input but using v-input component ... am I missing something? Commented Mar 15, 2018 at 20:18
  • I set the name property on the component to v-input Commented Mar 15, 2018 at 20:24
  • The <input> doesn't have a value or v-model binding, for starters. Commented Mar 15, 2018 at 20:35

2 Answers 2

5

To enable the use of v-model the inner component must take a value property.

Bind the value to the inner <input> using :value, not v-model (this would mutate the prop coming from the parent). And when the inner <input> is edited, emit an input event for the parent, to update its value (input event will update the variable the parent has on v-model).

Also, if you have a default value for the type prop, declare it in props, not in the template.

Here's how your code should be

<template>
    <input
        :type="type"
        :value="value"
        @input="$emit('input', $event.target.value)"
        class="v-input" />
</template>

<script>
export default {
    props: {
      type: {default() { return 'text'; }},
      value: {}                              // you can also add more restrictions here
    },
    name: 'v-input'
}
</script>

Info about what props can have: Components / Passing data With Props.

Demo below.

Vue.component('v-input', {
  template: '#v-input-template',
  props: {
    type: {default() { return 'text'; }},
    value: {}                              // you can also add more restrictions here
  },
  name: 'v-input'
});

new Vue({
  el: '#app',
  data: {
    something: "I'm something"
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>

<div id="app">
  <p>Parent something: {{ something }}</p>
  <hr>
  Child: <v-input v-model="something" />
</div>

<template id="v-input-template">
   <input
      :type="type"
      :value="value"
      @input="$emit('input', $event.target.value)"
      class="v-input" />
</template>

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I ended up doing something similar to this, but I didn't pass the value down as a prop. I see why you did it that way and I may change it in the future, but I would like to keep it as minimal as possible.
0

https://v2.vuejs.org/v2/guide/components.html#sync-Modifier

<template>
  <q-layout>
    <v-input :value.sync="something" />
  </q-layout>
</template>

<template>
    <input
    :type="type ? type : 'text'"
    v-model="inputVal"
    class="v-input"/>
</template>

<script>
export default {
    props: ['type', 'value'],
    name: 'v-input',
    data:function(){
        return {
            inputVal: ''
        };
    },
    watch:{
        value: function(newValue){
            this.$emit('update:value', newValue)
        }
    }
}
</script>

You need to pass your value to the input component using the .sync modifier so the changes will sync back to the parent.

2 Comments

You're modifying a prop by using v-model on it.
@RoyJ coming from vue 1 I had not realized the .sync modifier functionality had changed, thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.