0

I am using an NPM package, vue-tel-input. I created a separate component for that, like-

components/NPMPackages/VueTelInput/Index.vue

<script setup lang="ts">
import { VueTelInput } from 'vue-tel-input';
import 'vue-tel-input/vue-tel-input.css';

defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>
<template>
  <VueTelInput
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
  >
  </VueTelInput>
</template>

Now, I am importing this component inside my App.vue, like this-

<script setup lang="ts">
import NPMPackageVueTelInput from '@/components/NPMPackages/VueTelInput/Index.vue'

const phone = ref('');
</script>

<template>
  <NPMPackageVueTelInput v-model="phone"></NPMPackageVueTelInput>
</template>

But this code is not working. I am not able to type inside the input box, nothing is displaying.

Here is the types-definition for this package.

I am using the following environment-

Vue- 3.3.4
vite - 4.4.9
typescript - 5.1.6

If I do not make a common component, and use vue-tel-input directly inside App.vue, it works fine.

Any help would be great.

Neha Soni
  • 3,935
  • 2
  • 10
  • 32

1 Answers1

1

the value in this line:

@input="value => emit('update:modelValue', value)"

will return an InputEvent object, that's why you get that warning.

but I wrote your component in another way (it's not best practice but it works) I apologize for my messy code

here is my solution:

<script setup lang="ts">
import { ref, watch, onMounted } from "vue";
import { VueTelInput } from "vue-tel-input";
import "vue-tel-input/vue-tel-input.css";

// Props
const props = defineProps({
  modelValue: String,
});

// Events
const emit = defineEmits(["update:modelValue"]);

// Local State
const value = ref("");

// watch for change Local State
watch(value, (val) => {
  emit("update:modelValue", val);
});

// watch for change Props
watch(
  () => props.modelValue,
  (val) => {
    value.value = val;
  }
);

// set initial value
onMounted(() => {
  value.value = props.modelValue;
});
</script>

<template>
  <VueTelInput v-model="value"> </VueTelInput>
</template>


Update

you can install @vueuse/core package and then use useVModel hook

here is the modified code with this method:

<script setup lang="ts">
import { useVModel } from '@vueuse/core'
import { VueTelInput } from "vue-tel-input";
import "vue-tel-input/vue-tel-input.css";

const props = defineProps<{modelValue: string}>()
const emit = defineEmits(['update:modelValue'])
const data = useVModel(props, 'modelValue', emit)

</script>

<template>
  <VueTelInput v-model="data"> </VueTelInput>
</template>

Reference: useVModel - @vueuse/core

Mohammad Masoudi
  • 426
  • 4
  • 10
  • Thanks much for the answer. I understood your approach too but as you said its a bit confusing approach using watcher and local variables. The concern is why the above example is not working. Do you have any kind of suspect about that? – Neha Soni Aug 30 '23 at 09:23
  • 1
    I updated my answer in a simpler way I hope it helps (If you don't have any other child in your wrapper component, without any extra configuration the `v-model` will work but if you have more than one child in the component you should use one of those methods) – Mohammad Masoudi Aug 30 '23 at 16:26
  • Oh, yes. I get it now. Thanks. – Neha Soni Sep 01 '23 at 04:56