I have a HTML input field to enter some information:
<div id="fruitForm">
<div class="inputArea">
<label for="fruit0">Enter Fruit Name</label>
<input id="fruit0"></input>
</div>
</div>
<button #click="newInputField">Add More Fruit Input Fields</button>
<button #click="submit">Submit Fruit</button>
And then I handle that click event:
export default {
data() {
return {
}
},
methods: {
newInputField() {
//Create another input area for users to input fruits
},
submit() {
//Do something here
}
}
}
When a user selects the Add More Fruit Input Fields button, it should create a new input area so that the HTML looks like this:
<div id="fruitForm">
<div class="inputArea">
<label for="fruit0">Enter Fruit Name</label>
<input id="fruit0"></input>
</div>
<div class="inputArea">
<label for="fruit1">Enter Fruit Name</label>
<input id="fruit1"></input>
</div>
</div>
<button #click="newInputField">Add More Fruit Input Fields</button>
<button #click="submit">Submit Fruit</button>
Now, I've been using traditional DOM manipulation methods via vanilla Javascript to accomplish this... stuff like this:
const inputArea = document.getElementsByClassName('inputArea');
And then I change the id's of the input field, and then I use appendChild to add the new input field to the DOM.
So my question is: how should I be cloning this element with vuejs? I feel I'm not approaching this in the vuejs way. Should I be approaching this like a list and using v-for? Or something else?
Avoid direct DOM manipulations with Vue. You can use data property as a model for your template. The answer would be yes, you can and probably should use v-for for what you call cloning:
var demo = new Vue({
el: '#demo',
data: {
counter: 0,
inputs: [{
id: 'fruit0',
label: 'Enter Fruit Name',
value: '',
}],
},
methods: {
addInput() {
this.inputs.push({
id: `fruit${++this.counter}`,
label: 'Enter Fruit Name',
value: '',
});
}
}
});
<script src="https://unpkg.com/vue#2.5.16/dist/vue.js"></script>
<div id="demo">
<div class="inputArea" v-for="input in inputs" :key="input.id">
<label :for="input.id">{{input.label}}</label>
<input :id="input.id" v-model="input.value"></input>
</div>
<button #click="addInput">Add input</button>
</div>
Related
I generate so many input boxes on loop of article array.
article is array of objects. Input boxes values are set with "value" key in each object.
<div
v-for="(option, i) in this.article"
:key="i"
class="form-row"
>
<div class="col">
<input
v-model="option.value"
:label="'label '+i"
:name="'inputValue'+i"
type="text"
required
/>
</div>
</div>
<button #click="submit"></button>
<script>
export default {
name: 'Article',
data(){
return(
article:[
{id: 'art1', value: 'artValue1'},
{id: 'art2', value: 'artValue2'},
{id: 'art3', value: 'artValue3'}
// There are about 50 objects
]
)
},
methods:{
submit(){
// How get values of inputs?
}
}
}
</script>
How can I make the value of input change and update the object in vue?
I created a sample Single File Component based on your code. Look at my modifications. The 'magic' of Vue reactivity is that the 'article' data is updated in real time as you change the input values.
<template>
<div class="input-bound-object-array">
<div class="row">
<div class="col-md-6">
<form #submit.prevent="submitForm">
<div class="form-group" v-for="(option, i) in article" :key="i">
<label>{{ option.id }}</label>
<input type="text" class="form-control" v-model="option.value"
required />
</div>
<button type="submit" class="btn btn-secondary">Submit</button>
</form>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
article: [
{ id: 'art1', value: 'artValue1' },
{ id: 'art2', value: 'artValue2' },
{ id: 'art3', value: 'artValue3' }
// There are about 50 objects
]
}
},
methods: {
submitForm() {
// 'this.article' is updated as the input values are changed, so at this point
// you have the data changes, so you can process it as needed, i.e. POST to REST endpoint
console.log(this.article);
}
}
}
</script>
You forgot to return the object from data function and you can pass option to submit handler and print the input values.
// How get values of inputs? -> Do you mean all of the inputs or input where ever the button clicked or anything else. Below code is to handle individual input and submit handlers
<template>
<div
v-for="(option, i) in article"
:key="i"
class="form-row"
>
<div class="col">
<input
v-model="option.value"
:label="'label ' + i"
:name="'inputValue' + i"
type="text"
required
/>
</div>
<!-- <button #click="submit(option)">Submit</button> to handle individual inputs -->
</div>
<!-- <button #click="submitAll()">Submit All</button> to handle all inputs -->
</template>
<script>
export default {
name: 'Article',
data() {
return { // you missed this
article:[
{id: 'art1', value: 'artValue1'},
{id: 'art2', value: 'artValue2'},
{id: 'art3', value: 'artValue3'}
]
}
},
methods: {
submit(option) { // current option
console.log(option.id, option.value)
},
submitAll() {
console.log(this.article) // which will have update input values as
you're using `v-model`, check `values`
}
}
}
</script>
Demo Link here
I am using Vue-Multiselect plugin and want to know how I can auto populate additional input fields (customer_firstname and customer_email) when a user selects an item from the initial drop down?
Scenario: If the name exists in the database/drop-down list the user can then select that name and Vue will auto populate the rest of the input fields (taken from the options array). Else, if the name does not exist, the user can tag/create a new value for each additional input fields (e.g, customer_firstname, customer_email).
Here's my JSFIDDLE code with evertying working, just need help wiring up the ability to autopopulate the rest of the input fields based on the initial selection of the lastname dropdown.
Vue Template:
<div id="app">
<div>
Last Name:
<multiselect id="dontforget" v-model="customer_last_name" :options="options" placeholder="Select an existing customer or type to add a new one" label="lastname" :custom-label="customerSelectName" track-by="uid" :close-on-select="true" :clear-on-select="false" :hide-selected="true" :preserve-search="true" #select="onSelect" :taggable="true" #tag="addTag" :multiple="false" tag-placeholder="Add customer as new customer">
<template slot="singleLabel" slot-scope="props">{{ props.option.lastname }}</template>
<template slot="option" slot-scope="props">
<span style="font-weight: bold;">{{ props.option.lastname }}</span>, {{ props.option.firstname }} -- <small>{{props.option.email}}</small>
</template>
<template slot="noResult">no rsults brah</template>
</multiselect>
<pre class="language-json"><code>Data: {{ customer_last_name }}</code></pre>
<br>
<br>
<br>
<label for="customer_first_name_input">First Name:</label><br>
<input id="customer_first_name_input" type="text" v-model="customer_first_name" />
<br>
<label for="customer_emailt">Email:</label><br>
<input id="customer_email" type="email" v-model="customer_email" />
</div>
</div>
Vue Script:
new Vue({
components: {
Multiselect: window.VueMultiselect.default
},
data: {
customer_last_name: '',
customer_first_name: '',
customer_email: '',
options: [{"uid":"1","firstname":"John","lastname":"Doe","email":"johndoe#aol.com","phone":null,"c_organization":"ACME","c_title":null}, {"uid":"2","firstname":"Mary","lastname":"Smith","email":"msmith#aol.com","phone":null,"c_organization":"NBA","c_title":"Miss"}, {"uid":"3","firstname":"Mike","lastname":"Verlander","email":"asdafsdf#aol.com","phone":null,"c_organization":"MLB","c_title":"Mr"}]
},
methods: {
addTag (newTag) {
const parts = newTag.split(', ');
const tag = {
uid: this.options.length + 1,
firstname: parts.pop(),
lastname: parts.pop()
}
this.options.push(tag)
this.customer_last_name = tag;
},
customerSelectName (option) {
return `${option.lastname}, ${option.firstname}`
},
onSelect (option, uid) {
console.log(option, uid)
}
}
}).$mount('#app')
You pretty much have everything you need. Your method onSelect is appended to the select event of your multiselect, so you can just use it.
In your onSelect method, add these lines:
this.customer_first_name = option.firstname;
this.customer_email = option.email;
That will assign to your variables the properties of the object you get when you select an option.
I am generating a some checkbox dynamically. Now I need to create v-model dynamic.
<div class="form-group input-group">
<label class="form-group-title">DIETARY PREFERENCES</label>
<p>Please mark appropriate boxes if it applies to you and/or your family</p>
<div class="check-group" v-for="v in alldietry" :key="v">
<input type="checkbox" v-model="userinfo.{{#Here will be the value}}" value="" id="Vegetarian">
<label for="Vegetarian">{{v.title}}</label>
</div>
</div>
into the v-model I have try v-model="userinfo.{{xyz}}" its shows error.
You can't use {{ }} interpolation inside attributes.
The v-model value is a javascript expression, so instead of
v-model="userinfo.{{xyz}}"
you can just do
v-model="userinfo[xyz]"
as you would normally do in javascript when accessing a dynamic property of an object.
To bind dynamic object to model, you need to access to key shared by the model value and the set of data used to display your list.
let vm = new Vue({
el: '#app',
data: {
userinfo: {
0: '',
1: ''
}
},
computed: {
alldietry() {
return [
{
id: 0,
title: 'Title'
},
{
id: 1,
title: 'Title'
}
]
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app" class="form-group input-group">
<label class="form-group-title">DIETARY PREFERENCES</label>
<p>Please mark appropriate boxes if it applies to you and/or your family</p>
<div class="check-group" v-for="(v, index) in alldietry" :key="index">
<input type="checkbox" v-model="userinfo[v.id]" value="" :id="v.id">
<label :for="v.id">{{v.title}}</label>
</div>
{{ userinfo }}
</div>
I would like to edit a list of users using Vue.js. Each user has a name and an age. It seems that v-for is the right directive to work with lists and v-model is the right directive to bind the contents of an input to a particular element in the list.
So I tried to implement it like this:
new Vue({
el: '#exercise',
data: {
users: [{
name: "martin",
age: 32
}]
},
methods: {
add_user: function() {
this.users.push({
name: "",
age: ""
});
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="exercise">
<form id="list">
<div></div>
<div v-for="user in users">
<input v-model="user.name">
<input v-model="user.age">
<button #click="add_user">+</button>
</div>
</form>
</div>
However, once I click the button to add a new user, a new line with input fields is displayed only for a fraction of a second and then disappears, leaving the list of users containing only one element.
Please, could you tell me what am I doing wrong?
The reason is <button> with <form> when you're click button it does the request automatically so its refresh or disappear because it fails to try to use <a> or using <button #click.prevent="add_user" />
<div id="exercise">
<form id="list">
<div></div>
<div v-for="user in users">
<input v-model="user.name">
<input v-model="user.age">
<a #click="add_user">+</a> //solution
<button #click.prevent="add_user">+</button> //another solution
</div>
</form>
</div>
The button is submitting the form, add .prevent to stop the action:
new Vue({
el: '#exercise',
data: {
users: [{
name: "martin",
age: 32
}]
},
methods: {
add_user () {
this.users = [ ...this.users, {
name: "",
age: ""
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="exercise">
<form id="list">
<div v-for="(user, index) in users" :key="index">
<input v-model="user.name" :key="`name-${index}`">
<input v-model="user.age" :key="`age-${index}`">
</div>
<button #click.prevent="add_user">+</button>
</form>
</div>
You need to set tye type of the button, since it's inside a form it fallbacks to submit button.
Also, it's good to define a :key to help vue to tell the difference between one line to another on v-for.
new Vue({
el: '#exercise',
data: {
users: [{
id:new Date().getTime(),
name: "martin",
age: 32
}]
},
methods: {
add_user: function() {
this.users.push({
id:new Date().getTime(),
name: "",
age: ""
});
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="exercise">
<form id="list">
<div v-for="user in users" :key="user.id">
<input v-model="user.name">
<input v-model="user.age">
<button type="button" #click="add_user">+</button>
</div>
</form>
</div>
So I have 2 blocks of HTML, each containing 2 input fields and when submitting the form, I want to get all values from the inputs, and then create an object from the values...
As of know I've done it with plain vanilla JS and it works as it should, however if feels like to touching the DOM a bit to much, and also are very much depending on a specific DOM struckture, and therefore I was thinking there must be a better way, the VUE way so to speak, however im a bit stuck on how to do this the VUE way, which is why posting the question here in hope of getting some useful tips :)
HTML:
<form novalidate autocomplete="off">
<div class="input-block-container">
<div class="input-block">
<input type="text" placeholder="Insert name" name="name[]" />
<input-effects></input-effects>
</div>
<div class="input-block">
<input type="email" placeholder="Insert email address" name="email[]" />
<input-effects></input-effects>
</div>
</div>
<div class="input-block-container">
<div class="input-block">
<input type="text" placeholder="Insert name" name="name[]" />
<input-effects></input-effects>
</div>
<div class="input-block">
<input type="email" placeholder="Insert email address" name="email[]" />
<input-effects></input-effects>
</div>
</div>
<button class="button button--primary" #click.prevent="sendInvites"><span>Send</span></button>
</form>
JS:
methods: {
createDataObject() {
let emailValues = document.querySelectorAll('input[type="email"]');
emailValues.forEach((email) => {
let name = email.parentNode.parentNode.querySelector('input[type="text"]').value;
if(email.value !== "" && name !== "") {
this.dataObj.push({
email: email.value,
name
});
}
});
return JSON.stringify(this.dataObj);
},
sendInvites() {
const objectToSend = this.createDataObject();
console.log(objectToSend);
//TODO: Methods to send data to server
}
}
You can provide data properties for each of your inputs if you have static content.
data: function() {
return {
name1: '',
email1: '',
name2: '',
email2: ''
}
}
Then use them in your template:
<input type="text" placeholder="Insert name" v-model="name1" />
Access in method by this.name1
Try this
<div id="app">
<h1> Finds </h1>
<div v-for="find in finds">
<input name="name[]" v-model="find.name">
<input name="email[]" v-model="find.email">
</div>
<button #click="addFind">
New Find
</button>
<pre>{{ $data | json }}</pre>
</div>
Vue Component
new Vue({
el: '#app',
data: {
finds: []
},
methods: {
addFind: function () {
this.finds.push({ name: '', email: '' });
}
enter code here
}
});