Search code examples
javascriptvue.jsvuejs3vue-component

Passing input value to vue component


I'm new in vuejs and I was creating custom components for elements like buttons, links, inputs, etc. This is my input component-

<template>
  <div class="position-relative">
    <input
      :class="[{ 'pe-5': type === 'password' }, 'form-control p-2 rounded-3']"
      :type="inputType"
      :id="label ? slugify(label) : null"
      v-model="inputValue"
      v-bind="$attrs"
    />
    <CustomButton
      type="button"
      transparent
      class="position-absolute end-0 top-50 translate-y--50"
      v-if="type === 'password'"
      @click="togglePasswordVisibility"
    >
      <RemixIcon :icon="showPassword ? 'eye-off-line' : 'eye-line'" />
    </CustomButton>
  </div>
</template>

<script>
import RemixIcon from '../components/RemixIcon.vue';
import CustomButton from '../components/CustomButton.vue';

export default {
  components: {
    RemixIcon,
    CustomButton
  },
  props: {
    type: {
      type: String,
      default: 'text',
    },
    label: {
      type: String,
      default: '',
    },
  },
  data() {
    return {
      inputValue: '',
      showPassword: false,
    };
  },
  computed: {
    inputType() {
      return this.showPassword ? 'text' : this.type;
    },
  },
  methods: {
    togglePasswordVisibility() {
      this.showPassword = !this.showPassword;
    },
    slugify(str) {
      return str
        .toLowerCase()
        .trim()
        .replace(/[^\w\s-]/g, '')
        .replace(/[\s_-]+/g, '-')
        .replace(/^-+|-+$/g, '');
    },
  },
};
</script>

<style scoped></style>

When I use v-model on it, It doesn't work properly

<TextInput type="text" v-model="user_name" />

In this case user_name has a default value but It doesn't appear in input.

I want to use v-model with this input and make it useable.

I tried searching online and asked from AI tools but nothing worked for me.


Solution

  • As @jaromanda-x mentioned, I added :value in my custom component and triggered an $emit for updating value of input. This is the final result that I ended up with -

    <template>
      <div class="position-relative">
        <input
          :class="[{ 'pe-5': type === 'password' }, 'form-control p-2 rounded-3']"
          :type="inputType"
          :value="modelValue"
          @input="$emit('update:modelValue', $event.target.value)"
        />
        <CustomButton
          type="button"
          transparent
          class="position-absolute end-0 top-50 translate-y--50"
          v-if="type === 'password'"
          @click="togglePasswordVisibility"
        >
          <RemixIcon :icon="showPassword ? 'eye-off-line' : 'eye-line'" />
        </CustomButton>
      </div>
    </template>
    
    <script>
    import RemixIcon from '../components/RemixIcon.vue';
    import CustomButton from '../components/CustomButton.vue';
    
    export default {
      components: {
        RemixIcon,
        CustomButton
      },
      props: {
        type: {
          type: String,
          default: 'text',
        },
        label: {
          type: String,
          default: '',
        },
        modelValue: {
          type: String,
        }
      },
      emits: ['update:modelValue'],
      data() {
        return {
          inputValue: '',
          showPassword: false,
        };
      },
      computed: {
        inputType() {
          return this.showPassword ? 'text' : this.type;
        },
      },
      methods: {
        togglePasswordVisibility() {
          this.showPassword = !this.showPassword;
        },
      },
    };
    </script>
    
    

    Now I can use v-model on this component and It's working as expected.