3👍
✅
There are few things to fix:
-
PrimeVue component
InputText
has no propvalue
butmodelValue
(to supportv-model
) – InputText Docs + read Using v-model on Components to learn a difference betweenv-model
on native inputs vs custom components -
InputText
is not a nativeinput
element, so there is no point to listen for ainput
event. The component is emittingupdate:modelValue
event. Also event payload is not native event soevent.target.value
makes no sense, just usevalue
– source -
There is no point in duplicating the
p-filled
asInputText
does this already (see source above)
// FormInput.vue
<template>
<span :class="wrapperClass">
<i :class="iconLeft" v-if="iconLeft" />
<InputText
:type="type"
:modelValue="modelValue"
@update:model-value="onInput"
/>
<label for="username">{{ label }}</label>
<i :class="iconRight" v-if="iconRight" />
</span>
</template>
<script lang="ts">
import InputText from "primevue/inputtext"
import { defineComponent } from "vue"
export default defineComponent({
name: "FormInput",
emits: ["update:modelValue"],
components: { InputText },
props: {
iconLeft: {
type: String,
default: "",
},
iconRight: {
type: String,
default: "",
},
error: {
type: String,
default: "",
},
label: {
type: String,
default: "",
},
type: {
type: String,
default: "text"
},
modelValue: {
type: String,
required: true
},
},
computed: {
wrapperClass(): any {
return {
"p-float-label": true,
"p-input-icon-left": this.iconLeft,
"p-input-icon-right": this.iconRight,
}
},
},
methods: {
onInput(value: any): any {
this.$emit("update:modelValue", value)
},
},
})
</script>
Usage:
<FormInput v-model="data" />
<!-- OR -->
<FormInput :modelValue="data" @update:model-value="data = $event" />
Demo:
const app = Vue.createApp({
data() {
return {
text: "default value",
}
},
});
app.component('FormInput', {
emits: ["update:modelValue"],
components: {
'inputtext': primevue.inputtext
},
template: `
<span :class="wrapperClass">
<i :class="iconLeft" v-if="iconLeft" />
<inputtext
:type="type"
:modelValue="modelValue"
@update:model-value="onInput"
></inputtext>
<label for="username">{{ label }}</label>
<i :class="iconRight" v-if="iconRight" />
</span>
`,
props: {
iconLeft: {
type: String,
default: "",
},
iconRight: {
type: String,
default: "",
},
error: {
type: String,
default: "",
},
label: {
type: String,
default: "",
},
type: {
type: String,
default: "text"
},
modelValue: {
type: String,
required: true
},
},
computed: {
wrapperClass() {
return {
"p-float-label": true,
"p-input-icon-left": this.iconLeft,
"p-input-icon-right": this.iconRight,
}
},
},
methods: {
onInput(value) {
this.$emit("update:modelValue", value)
},
},
});
app.mount('#app');
<link href="https://unpkg.com/primevue/resources/themes/saga-blue/theme.css" rel="stylesheet">
<link href="https://unpkg.com/primevue/resources/primevue.min.css" rel="stylesheet">
<link href="https://unpkg.com/primeicons/primeicons.css" rel="stylesheet">
<script src="https://unpkg.com/vue@next"></script>
<script src="https://unpkg.com/primevue/inputtext/inputtext.min.js"></script>
<div id="app">
<form-input v-model="text"></form-input>
<pre>
{{ text }}
</pre>
</div>
Source:stackexchange.com