I'm trying to write a custom form control in Vue.js to learn how to package together multiple form inputs into a single custom component.
My project setup looks like this (standard webpack-simple vue cli setup):
$ tree -L 1
.
├── README.md
├── index.html
├── node_modules
├── package.json
├── src
└── webpack.config.js
Here's my top level Vue instance .vue file:
// App.vue
<template>
<div class="container">
<form v-if="!submitted" >
<div class="row">
<div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3">
<form>
<fullname v-model="user.fullName"></fullname>
<div class="form-group">
<label for="email">Email:</label>
<input id="email" type="email" class="form-control" v-model="user.email">
<label for="password">Password:</label>
<input id="password" type="password" class="form-control" v-model="user.password">
</div>
<fieldset class="form-group">
<legend>Store data?</legend>
<div class="form-check">
<label class="form-check-label">
<input type="radio" class="form-check-input" name="storeDataRadios" id="storeDataRadios1" value="true" checked v-model="user.storeData">
Store Data
</label>
</div>
<div class="form-check">
<label class="form-check-label">
<input type="radio" class="form-check-input" name="storeDataRadios" id="storeDataRadios2" value="false" v-model="user.storeData">
No, do not make my data easily accessible
</label>
</div>
</fieldset>
</form>
<button class="btn btn-primary" @click.prevent="submitForm()">Submit</button>
</div>
</div>
</form>
<hr>
<div v-if="submitted" class="row">
<div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3">
<div class="panel panel-default">
<div class="panel-heading">
<h4>Your Data</h4>
</div>
<div class="panel-body">
<p>Full Name: {{ user.fullName }}</p>
<p>Mail: {{ user.email }}</p>
<p>Password: {{ user.password }} </p>
<p>Store in Database?: {{ user.storeData }}</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import FullName from './FullName.vue';
export default {
data() {
return {
user: {
fullName: 'John Smith',
email: '',
password: '',
storeData: true,
},
submitted: false
}
},
methods: {
submitForm() {
this.submitted = true;
},
},
components: {
'fullname' : FullName,
}
}
</script>
<style>
</style>
And here's the custom component file:
<template>
<div class="form-group">
<label for="firstName">First name:</label>
<input id="firstName" type="text" class="form-control" :value="first" @input="emitChange(true, $event)">
<label for="lastName">Last name:</label>
<input id="lastName" type="text" class="form-control" :value="last" @input="emitChange(false, $event)">
</div>
</template>
<script>
export default {
props: ['value'],
methods: {
emitChange(isFirst, evt) {
let name = '';
let evtValue = evt.target.value == undefined ? "" : evt.target.value;
if (isFirst) {
name = evtValue +" "+ this.second;
} else {
name = this.first +" "+ evtValue;
}
this.value = name;
this.$emit('input', this.value);
}
},
computed: {
first() {
if (this.value != "")
return this.value.split(" ")[0];
else return "";
},
last() {
if (this.value != "")
return this.value.split(" ")[1];
else return "";
}
}
}
</script>
Which I also realize I'm messing up because I'm directly editing a prop value with:
this.value = name;
(not an error, but Vue.JS gives a warning).
However, even before that, typing in the first input box causes the second input box to update its value to undefined (...wat!?).
Would be grateful for advice on how to properly set up custom form control components! (and why this example isn't working).