Vue.js add filename dynamically in a v-for loop - javascript

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

redirecting to different page with form submit in VUE JS

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>

nuxtjs with simple-vue-validator as plugin

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>

Methods in Components in Vue js

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

passing data between components in vuejs

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>

Vue/Jquery override two-way data bidning

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>

Categories

Resources