I have a component that dynamically adds inputs to my application. One input is a text input and another is a file input. In the case of text input everything works, I take the value via v-model. In the case of file input it is not possible to use v-model, instead v-on: change is used. How do I add the filename to the lists object dynamically?
Template
<template lang="html">
<div v-for="list in lists">
<input type="text" v-model="list.text" >
<input type="file" #change="upload">
</div>
<button #click="addItem">Add Item</button>
</template>
Script
<script>
export default {
data() {
return {
lists:[{text: '', filename: '',}]
}
},
methods: {
addItem() {
this.lists.push({ text: '', filename: '' })
},
upload(event) {
this.lists.filename = event.target.files[0].name
},
}
}
</script>
I'm using Vue 3.
Thanks in advance.
You can iterate with the index as well, then pass the index to the upload function, like this:
<script>
export default {
data() {
return {
lists:[{text: '', filename: '',}]
}
},
methods: {
addItem() {
this.lists.push({ text: '', filename: '' })
},
upload(event, index) {
this.lists[index].filename = event.target.files[0].name
},
}
}
</script>
<template lang="html">
<div v-for="(list, index) in lists">
<input type="text" v-model="list.text" >
<input type="file" #change="upload($event, index)">
</div>
<button #click="addItem">Add Item</button>
</template>
You can bind with array index, do not need upload method
new Vue({
el: '#app',
data() {
return {
title: "Vue app",
lists:[{text: '', filename: '',}]
};
},
methods:{
addItem() {
this.lists.push({ text: '', filename: '' })
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"><h2>{{title}}</h2>
<div v-for="(list,i) in lists">
<input type="text" v-model="lists[i].text" >
<input type="file" v-model="lists[i].filename">
</div>
<button #click="addItem">Add Item</button>
<pre>{{lists}}</pre>
</div>
You can do it like this:
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<input id='inputfile' type='file' name='inputfile' onChange='getoutput()'>
new Vue({
el: '#app',
data() {
return {
title: "Vue app",
lists:[{text: '', filename: '',}]
};
},
methods:{
addItem() {
this.lists.push({ text: '', filename: '' })
},
getFile(filePath) {
return filePath.substr(filePath.lastIndexOf('\\') + 1).split('.')[0];
},
getoutput(e, index) {
let fileName = this.getFile(e.target.value);
let fileExtention = e.target.value.split('.')[1];
this.lists[index].filename = `${fileName}.${fileExtention}`;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"><h2>{{title}}</h2>
<div v-for="(list,i) in lists">
<input type="text" v-model="lists[i].text" >
<input type="file" #change="getoutput($event, i)">
</div>
<button #click="addItem">Add Item</button>
<pre>{{lists}}</pre>
</div>
Related
I am trying to submit form which will redirect to different page containing post request data . Basically I hit redirectCompo component from another component
return this.$router.push({path: '/form-submit-component'});
form submit component but it's not redirecting
<template>
<div style="visibility: hidden;">
<form name="PostForm" id="PostForm" method="POST" action="www.google.com">
<input type="text" name="email_id" value="xyz#gmail.com">
<input type="text" name="gender" value="male">
</form>
</div>
</template>
<script>
export default {
name: 'redirectCompo',
computed: {},
components: {},
data: function () {
return {}
},
mounted() { },
created() {
document.getElementById("PostForm").submit();
},
methods: {},
}
</script>
<template>
<div>
<form name="PostForm" id="PostForm" method="POST" action="www.google.com">
<input type="text" name="email_id" value="xyz#gmail.com" />
<input type="text" name="gender" value="male" />
<button type="submit">submit</button>
</form>
</div>
</template>
<script>
export default {
name: "redirectCompo",
computed: {},
components: {},
created() {
this.submit();
},
methods: {
submit() {
console.log("form has been submitted");
this.$router.push({ path: "/home" });
},
},
data: function () {
return {};
},
};
</script>
I am new to Vue and Nuxt and I am building simple forms with simple-vue-validator for validating the form before I submit it to the back-end. I did follow the Nuxtjs plugin's documentation but I am getting some errors ๐
The error I am getting is TypeError: Cannot read property 'Validator' of undefined.
I can't find any $SimpleValidator on this. Not sure if I did something wrong or forgot something, but I keep reading the documentation and this is all I understand. Thanks in advance.
./plugins/simple-validator.js
import Vue from 'vue'
import SimpleValidator from 'simple-vue-validator'
Vue.use(SimpleValidator)
./nuxt.config.js
export default {
...
plugins: [
{ src: '#/plugins/simple-validator.js', ssr: true }
],
...
}
./pages/index.vue*
<template>
<form>
<div class="field-holder">
first name *
<input type="text" v-model="formValues.firstName" :value="formValues.firstName" />
<span v-if="validation.hasError('firstName')">
{{ validation.firstError('firstName') }}
</span>
</div>
<div class="field-holder">
middle name
<input type="text" v-model="formValues.middleName" :value="formValues.middleName" />
</div>
<div class="field-holder">
last name *
<input type="text" v-model="formValues.lastName" :value="formValues.lastName" />
<span v-if="validation.hasError('lastName')">
{{ validation.firstError('lastName') }}
</span>
</div>
<button #click="submit">Submit</button>
</form>
</template>
<script>
export default {
data () {
formValues: {
firstName: '',
middleName: '',
lastName: ''
}
},
validators: {
'formValues.firstName' (value) {
return this.$SimpleValidator.Validator.value(value).required()
},
'formValues.lastName' (value) {
return this.$SimpleValidator.Validator.value(value).required()
}
},
methods: {
submit (event) {
event.preventDefault()
this.$validate()
.then(function (success) {
if (success) {
console.log('Validation succeeded!')
}
})
}
}
}
</script>
I fixed my issue! ๐
We just need to add import { Validator } from 'simple-vue-validator' to the component that requires it. So the updated component will look like this:
./pages/index.vue
<template>
<form>
<div class="field-holder">
first name *
<input type="text" v-model="formValues.firstName" :value="formValues.firstName" />
<span v-if="validation.hasError('firstName')">
{{ validation.firstError('firstName') }}
</span>
</div>
<div class="field-holder">
middle name
<input type="text" v-model="formValues.middleName" :value="formValues.middleName" />
</div>
<div class="field-holder">
last name *
<input type="text" v-model="formValues.lastName" :value="formValues.lastName" />
<span v-if="validation.hasError('lastName')">
{{ validation.firstError('lastName') }}
</span>
</div>
<button #click="submit">Submit</button>
</form>
</template>
<script>
import { Validator } from 'simple-vue-validator'
export default {
data () {
formValues: {
firstName: '',
middleName: '',
lastName: ''
}
},
validators: {
'formValues.firstName' (value) {
return Validator.value(value).required()
},
'formValues.lastName' (value) {
return Validator.value(value).required()
}
},
methods: {
submit (event) {
event.preventDefault()
this.$validate()
.then(function (success) {
if (success) {
console.log('Validation succeeded!')
}
})
}
}
}
</script>
The following code gives me some next error.
All I'm trying to do is input data, then the button should do an alert and output the data that's inputted.
<template>
<div class="hello">
<h1> {{ greeting }} </h1>
<label for="value"> Name </label>
<input type="text" v-model="value" placeholder="input name">
<button type="submit" v-on:click="clickHandler" class="btn btn-primary">Submit</button>
</div>
</template>
<script src="./main.js"></script>
<script>
export default {
name: 'input-data',
data: function() {
return {
value: String,
greeting: "Welcome to Heaven Stranger"
}
},
methods: {
clickHandler: function() {
alert("Name of SIR: " + value);
}
}
}
methods: {
clickHandler: function() {
alert("Name of SIR: " + this.value);
}
}
here your code to sandbox and play
I've got my expense tracker app. I've got problem with adding Expense.
I've got two components responsible for this: addCategory.vue and selectCategory.vue.
This is my selectCategory.vue component:
<template>
<div>
<select class="custom-select" #selected="this.$emit('select-cat',category)">
<option v-for="category in categories">{{ category.title }}</option>
</select>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
categories: [],
errors: []
}
},
created() {
axios.get(`http://localhost:3000/categories`)
.then(response => {
this.categories = response.data;
console.log(response.data);
})
.catch(e => {
this.errors.push(e)
})
}
}
</script>
and this is my addExpense.vue component:
<template>
<div class="card">
<div class="card-header">
<h4>Dodaj nowy wydatek</h4>
</div>
<form v-on:submit.prevent="addExpense">
<div class="card-body">
<div class="form-group">
<label for="expense-name">Nazwa wydatku</label>
<input type="text" class="form-control" id="expense-name" v-model="Expense.title">
</div>
<div class="form-group">
<label for="expense-amount">Wartoลฤ</label>
<input type="number" class="form-control" id="expense-amount" v-model="Expense.amount">
</div>
<div class="form-group">
<label for="expense-date">Data wydatku</label>
<input type="date" class="form-control" id="expense-date" v-model="Expense.date">
</div>
<div class="form-group">
<label for="expense-category">Kategoria</label>
<select-category #select-cat="chooseCategory" v-model="Category.id"></select-category>
</div>
<br>
<div class="form-group">
<button class="btn btn-primary" #click="showAlert">Dodaj nowy wydatek</button>
</div>
</div>
</form>
</div>
</div>
</template>
<script>
import axios from 'axios';
import selectCategory from './selectCategory.vue';
export default {
components: {
'select-category': selectCategory
},
data(){
return {
Expense: {
title:'',
amount: '',
date:'',
categoryId:''
},
}
},
methods : {
chooseCategory(){
this.Expense.categoryId = this.Category.id
},
showAlert(){
this.$alert.success({
message: 'Wydatek dodany poprawnie'
})
},
addExpense(){
let newExpense = {
title : this.Expense.title,
amount : this.Expense.amount,
date : this.Expense.date,
categoryId: this.Expense.categoryId
}
console.log(newExpense);
axios.post(`http://localhost:3000/expenses`, newExpense)
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
})
}
}
}
</script>
I need help because when I try to add the Expense, field with 'categoryId' remains empty.
I use Events to pass the name of categories but I dont know how to add category.id to Expense.
The issues in your codes:
you need to add one data property to save which option the user selected, so add one data property=selectedCategory
you didn't bind the value for the options of the select, and you didn't bind the value of the select, so add v-model="selectedCategory" for <select> and add :value="category" for <option>
It seems you bind wrong event (event=selected more likely is the event name you customized) for <select>, change to #change="selectChange(selectedCategory)"
Finally, in addExpense.vue, listen event=select-cat.
Like below demo:
Vue.config.productionTip = false
Vue.component('select-category', {
template: `<div>
<select class="custom-select" v-model="selectedCategory" #change="selectChange(selectedCategory)">
<option v-for="category in categories" :value="category">{{ category.title }}</option>
</select>
</div>`,
data() {
return {
categories: [],
errors: [],
selectedCategory: null
}
},
mounted() {
this.categories = [
{'id':1, 'title': 'abc'},
{'id':2, 'title': 'xyz'}
]
},
methods: {
selectChange: function(newCatetory) {
this.$emit('select-cat',newCatetory)
}
}
})
new Vue({
el: '#app',
data() {
return {
categorySelected: null
}
},
watch: {
categorySelected: function (newVal, oldVal) {
console.log('changed to ' + newVal.id + ' from ' + (oldVal ? oldVal.id : oldVal))
}
},
methods:{
chooseCategory: function(data) {
this.categorySelected = data
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<div class="form-group">
<label for="expense-category">Kategoria</label>
<select-category #select-cat="chooseCategory($event)"></select-category>
</div>
</div>
I have an input in a Vue.js component that I need to override using jquery. I need to fill an input with an email address using jquery. When I press fill in email jQuery will populate the email input. But when I use V-model this it is not updated. Is there a workaround for this?
Here is a working jsfiddle example
https://jsfiddle.net/s3b7f1ah/
Here is the HTML
<button id="push-email">Fill in email</button>
<br><br>
<div id="root">
<label for="name">Name</label>
<input type="text" name="name" id="name" v-model="name">
<label for="name">Email</label>
<input type="text" name="email" id="email" v-model="email">
<br><br>
<button #click="proceed">next</button>
<br><br>
{{ name }} <br>
{{ email }}
</div>
Here is the jQuery
//jQuery
$(function() {
$('#push-email').click(function() {
$('#email').val("john#example.com");
});
});
And here is the vue component
//Vue
var app = new Vue({
el: '#root',
data: {
name: '',
email: '',
},
methods: {
proceed: function () {
}
},
});
https://jsfiddle.net/s3b7f1ah/
The best way if you really are stuck would be to add an event listener in your vue model:
var app = new Vue({
el: '#root',
data: {
name: '',
email: '',
},
methods: {
proceed: function () {
},
foo : function(event){
this.email = event.target.value;
}
},
});
<input #change="foo" type="text" name="email" id="email" v-model="email">
This way, you don't have to modify the jQuery logic.
Updated jsfiddle: https://jsfiddle.net/s3b7f1ah/1/
Change you jquery code to set the model value instead and it will get reflected in the input field.
//jQuery
$(function() {
$('#push-email').click(function() {
app.email = 'john#example.com';
});
});
You could write a directive to handle the jQuery change (as long as jQuery issues one). If jQuery just sets the value without triggering a change event, you'll never see it. Borrowing code from Axnyff:
//Vue
var app = new Vue({
el: '#root',
data: {
name: '',
email: '',
},
methods: {
proceed: function() {
},
foo: function(event) {
this.email = event.target.value;
}
},
directives: {
onJqueryChange: {
bind(el, binding) {
$(el).change(binding.value);
}
}
}
});
//Jquery
$(function() {
$('#push-email').click(function() {
$('#email').val("john#example.com").change();
});
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="push-email">Fill in email</button>
<br>
<br>
<div id="root">
<label for="name">Name</label>
<input type="text" name="name" id="name" v-model="name">
<label for="name">Email</label>
<input v-on-jquery-change="foo" type="text" name="email" id="email" v-model="email">
<br>
<br>
<button #click="proceed">next</button>
<br>
<br> {{ name }}
<br> {{ email }}
</div>