Reputation: 1152
for me NuxtJS application i've got multiple components thats come together in one form. Here the code:
AppButton.vue
<template>
<button
class="button"
:class="btnStyle"
:disabled="disabled"
v-bind="$attrs"
v-on="$listeners"><slot /></button>
</template>
<script>
export default {
name: 'AppButton',
props: {
btnStyle: {
type: String,
default: ''
},
disabled: {
type: String
}
}
}
</script>
AppFormInput.vue
<template>
<div class="form-input">
<input
v-bind="$attrs"
:name="name"
:value="value"
:type="type"
:placeholder="placeholder"
:max="max"
:min="min"
:pattern="pattern"
:required="required"
:disabled="disabled"
@input="$emit('input', $event.target.value)">
</div>
</template>
<script>
export default {
name: 'AppFormInput',
props: {
controlType: {
type: String,
default: 'input'
},
name: {
type: String
},
value: {
type: String,
default: ''
},
type: {
type: String,
default: ''
},
placeholder: {
type: String,
default: ''
},
max: {
type: String
},
min: {
type: String
},
pattern: {
type: String
},
required: {
type: String,
},
disabled: {
type: String
}
}
}
</script>
FormGroup.vue
<template lang="html">
<div class="form-group">
<AppLabel :label="label"/>
<AppFormInput :v-bind="$attrs"/>
</div>
</template>
<script>
import AppLabel from '~/components/atoms/AppLabel'
import AppFormInput from '~/components/atoms/AppFormInput'
export default {
components: {
AppLabel,
AppFormInput
},
props: {
label: {
type: String,
default: 'Form Label'
}
}
}
</script>
Form.vue
<template lang="html">
<form @submit.prevent="onSave">
<FormGroup label="Form Input" v-model="formPosts.forminput"/>
<FormGroup label="Form Input Disabled" disabled="disabled" v-model="formPosts.forminputdisabled"/>
<FormGroup label="Form Input With Placeholder" placeholder="Set placeholder" v-model="formPosts.forminputplaceholder"/>
<FormGroup label="Form Input Required" required="required" v-model="formPosts.forminputrequired"/>
<FormGroup label="Form Email" type="email" v-model="formPosts.forminputemail"/>
<FormGroup label="Form Date" type="date" v-model="formPosts.forminputdate"/>
<FormGroup label="Form Number" type="number" value="1" min="1" max="5" v-model="formPosts.forminputnumber"/>
<FormGroup label="Form Tel" type="tel" pattern="\d{3}-\d{3}-\d{4}" placeholder="XXX-XXXX-XXXX" v-model="formPosts.forminputtel"/>
<!--Add Select normal and disabled-->
<FormGroup label="Form Radio" type="radio" value="1" v-model="formPosts.forminputradio"/>
<FormGroup label="Form Checkbox" type="checkbox" value="2" v-model="formPosts.forminputcheckbox"/>
<AppButton type="submit" btn-style="btn-brand">Save</AppButton>
</form>
</template>
<script>
import FormGroup from '~/components/molecules/FormGroup'
import AppButton from '~/components/atoms/AppButton'
export default {
components: {
FormGroup,
AppButton
},
data() {
return{
formPosts: {
forminput: '',
forminputdisabled: '',
forminputplaceholder: '',
forminputrequired: '',
forminputemail: '',
forminputdate: '',
forminputnumber: '',
forminputtel: '',
forminputradio: '',
forminputcheckbox: '',
}
}
},
methods: {
onSave() {
console.log(this.formPosts);
this.$emit('submit', this.formPosts)
},
}
}
</script>
At least, the index.vue
<template lang="html">
<div class="container">
<h1>Forms</h1>
<Form @submit="onSubmitted"/>
</div>
</template>
<script>
import Form from '~/components/organism/Form'
export default {
components: {
Form
},
methods: {
onSubmitted(data){
console.log(data);
}
}
}
</script>
when the form is submitted the fields stays empty. The required field must have a value for example but it stays empty. I think that the some components not have access through the value of the field. Does anyone have tips?
Thanx for any help
Upvotes: 0
Views: 958
Reputation: 135762
$attrs
(in v-bind="$attrs"
) will only bind attributes, not props (bold is mine):
vm.$attrs
: Contains parent-scope attribute bindings (except forclass
andstyle
) that are not recognized (and extracted) as props. When a component doesn't have any declared props, this essentially contains all parent-scope bindings (except forclass
andstyle
), and can be passed down to an inner component viav-bind="$attrs"
- useful when creating higher-order components.
You need to set the props yourself in FormGroup.vue.
In FormGroup.vue, declare the value
prop so you can use in the template:
<script>
import AppLabel from '~/components/atoms/AppLabel'
import AppFormInput from '~/components/atoms/AppFormInput'
export default {
components: {
AppLabel,
AppFormInput
},
props: {
label: {
type: String,
default: 'Form Label'
},
value: { // added this
type: String // added this
} // added this
}
}
</script>
In FormGroup.vue, Add :value="value" @input="$emit('input', $event)"
to the template.
<template lang="html">
<div class="form-group">
<AppLabel :label="label"/>
<AppFormInput :v-bind="$attrs" :value="value" @input="$emit('input', $event)" />
</div>
</template>
The code above will set <AppFormInput>
's value and will propagate (up) it's input
event. Not the v-model
s in Form.vue should work.
Upvotes: 1