Vue component Button doesn't works - javascript

Why does it work on the first, and it doesn't work on the second?
First row work: https://imgur.com/b45QlU3
Last row doesn't work: https://imgur.com/S79Gq5M
vue:
<template>
<div>
<div class="form-group" v-for="(input,index) in inputs" :key="index">
<input type="text" name="medicine[]" class="form-control">
<span>
Add
Remove
</span>
</div>
</div>
</template>
<script type="text/javascript">
export default{
data(){
return{
inputs:[{}]
}
},
methods:{
add(){
this.inputs.push({
medicine:''
})
},
remove(index)
{
this.inputs.splice(index,1)
}
}
}
</script>

Related

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

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>

Failed to mount component: template or render function not defined using vue.js

I'm learning vue. js .I'm trying to make simple form by using vue.js but I got above error while making a form. I tried but unable to fix the problem.
Please help me.
<div id="app">
<form name="form" #submit.prevent="handleLogin">
<input
v-model="fiscal_year"
v-validate="'required'"
type="text"
class="form-control"
name="fiscal_year"
/>
<button class="btn btn-primary btn-block" :disabled="loading">
<span v-show="loading" class="spinner-border spinner-border-sm"></span>
<span>Submit</span>
</button>
</form>
<script>
var app = new Vue({
el: '#app',
data: {
fiscal_year: 2000,
loading: false,
},
mount:function(){},
methods: {
handleLogin(){
console.log('handle login');
this.loading = true;
}
}
})
</script>
UPDATE
If you are using cli-vue : https://cli.vuejs.org/
Assume you put file in App.vue :
<template>
<div id="app">
<h1>hello</h1>
<form name="form" #submit.prevent="handleLogin">
<input v-model="fiscal_year" type="text" class="form-control" name="fiscal_year">
<button class="btn btn-primary btn-block" :disabled="loading">
<span v-show="loading" class="spinner-border spinner-border-sm"></span>
<span>Submit</span>
</button>
</form>
</div>
</template>
<script>
export default {
data() {
return {
fiscal_year: 2000,
loading: false
};
},
methods: {
handleLogin() {
console.log("handle login");
this.loading = true;
}
}
};
</script>
Dont use jquery in Vue project. If you want to use bootstrap you can use bootsrap-vue : https://bootstrap-vue.js.org/
But if you are using vue in html use this : https://v2.vuejs.org/v2/guide/
-- Previous --
First, have you read vuejs introduction in https://v2.vuejs.org/v2/guide/ and Vue Lesson on Scrimba ?
About the question. <template> are used in component. You can replace it to <div id="app"> :
<div id="app"> <!-- Replace <template> with <div> -->
<div class="col-md-12">
<form name="form" #submit.prevent="handleLogin">
<div class="form-group col-md-6">
<label for="fiscal_year">Fiscal Year</label>
<input
v-model="fiscal_year"
v-validate="'required'"
type="text"
class="form-control"
name="fiscal_year"
/>
</div>
<div class="form-group">
<button class="btn btn-primary btn-block" :disabled="loading">
<span v-show="loading" class="spinner-border spinner-border-sm"></span>
<span>Submit</span>
</button>
</div>
</form>
</div>
</div>
Then you create vue instance in the <script> tag :
var app = new Vue({
el: '#app',
data: {
fiscal_year: 2000,
loading: false,
},
methods: {
handleLogin(){
console.log('handle login');
this.loading = true;
}
}
In the script of your component or vue instance try to add fiscal_year :
export default{
...
data(){
return{
fiscal_year:null,
....
}
}
....
}
or in a Vue instance :
new Vue ({
el:"#app",
data(){
return{
fiscal_year:null,
....
}
}
...
})
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
<form name="form" #submit.prevent="handleLogin">
<input
v-model="fiscal_year"
v-validate="'required'"
type="text"
class="form-control"
name="fiscal_year"
/>
<button class="btn btn-primary btn-block" :disabled="loading">
<span v-show="loading" class="spinner-border spinner-border-sm"></span>
<span>Submit</span>
</button>
</form>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
fiscal_year: 2000,
loading: false,
},
mount:function(){},
methods: {
handleLogin(){
console.log('handle login');
this.loading = true;
}
}
})
</script>

Where/How to define a submit destination for my self created form (Vue) component?

I want to re-use a form component through my website, but the submit button will have to handle different things every time (display different data, depending which page is calling the form-component)
I'm a little bit new to paying around with Vue components and passing data between them, up until now I did messy one-page apps.
My current plan is have the form get the inputs/filters (from the form component), and when clicking submit, it should send this data (somehow?) to the element that called it - and will know how to handle it to the specific case from where it was called. I hope this is the right approach to this kind of scenario (?).
Is my plan a proper use of Vue / a proper way to submit a form from an external form-component?
In what way do I trigger the submit to send data / run a method outside of my DashboardForm.vue component?
How do I send fetched data of DashboardForm.vue component from ReportType1.vue and re-use this functionality in ReportType2.vue.
This is my Vue Form component (DashboardForm.vue):
<template>
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body">
<form id="mainForm" class="form-material row" method="POST">
<div class="" id="date-range">
<datepicker v-model="startDate" input-class="form-control inputDate" placeholder="Start Date" required></datepicker>
<div class="input-group-append">
<span class="input-group-text b-0 text-white"> to </span>
</div>
<datepicker v-model="endDate" input-class="form-control inputDate" placeholder="End Date" required></datepicker>
<input type="button" class="btn btn-info waves-effect waves-light" v-on:click="groupFilterDisplay(true);" value="Filter by Group"/>
<!-- <input type="button" id="submit-btn" class="btn btn-success waves-effect waves-light" v-on:click="loadNew" value="Submit"/> -->
<input type="button" id="submit-btn" class="btn btn-success waves-effect waves-light" value="Submit"/>
</div>
</form>
</div>
</div>
</div>
<transition name="fade">
<div id="groupFilter" class="popupGroupFilter" v-if="groupFilter">
<div id="filterArea">
<input type="text" v-model="searchGroupInput" placeholder="Search" class="gfSearch">
<span class="gfTitle">Filter by Group</span>
<hr>
</div>
<div class="ulTree">
<ul>
<tree_item class="item" v-bind:model="groupTree"></tree_item>
</ul>
</div>
<div v-on:click="applyGroupFilter();" class="gfClose gfApply"><span>✔ Apply</span></div>
<div v-on:click="groupFilterDisplay(false);" class="gfClose"><span>X Close</span></div>
</div>
</transition>
</div>
</template>
<script>
// import { GF } from '../mixins/GF.js';
export default {
name: 'DashboardForm',
// mixins: [GF],
data() {
return {
groupTree: window.groups,
searchGroupInput: '',
searchGroupArray: [],
groupFilterApplied: false,
groupFilterBackup: [],
selectedIds: [],
groupFilter: false,
startDate: null,
endDate: null,
mode: 0,
}
},
props: {
options: Array
},
watch: {
'searchGroupInput': function (newVal, oldVal) {
this.groupTree = this.searchGroupResult();
}
},
methods: {
recurseGroups: function (arr, action) {
},
applyGroupFilter: function () {
},
groupFilterDisplay: function (display) {
},
searchGroupResult: function () {
},
fetchGroupIds: function () {
}
}
};
</script>
This is the component that uses the DashboardForm for example (
ReportType1.vue):
<script>
import DashboardForm from "../tools/DashboardForm.vue";
export default {
components: {
DashboardForm
},
data() {
return {
};
},
created() {
},
mounted() {
},
destroyed() {
},
watch: {
},
methods: {
}
}
</script>
<!-- Template -->
<template>
<div>
<!-- Form -->
<DashboardForm/>
<!-- form result -->
<div id="resultContainer"> <datatable/> </div>
</div>
</template>
Okay if I understood you well, we are trying to build a reusable form component.
I will give you a quick overview of how VUE components communicate.
The component takes its necessary inputs using the props.
The component inner HTML can be passed from its user by using slot.
The component fire events to tell its user that there is something happened inside me.
Example of the three cases:
Your component my-form template:
<form>
<div class="row">
<slot></slot>
</div>
<div class="row">
<div class="col-12">
<button type="button" class="btn btn-default" #click="onSubmit"></button>
<button v-if="hasReset" class="btn btn-danger" #click="onReset"></button>
</div>
</div>
</form>
Your component js file:
export default {
name: 'my-form',
data() {
return {
}
},
props: {
reset: boolean
},
computed: {
hasReset: function(){
return this.reset;
}
}
methods: {
onSubmit: function(){
let data = { "name": "dummy data" };
this.$emit("submit", data);
},
onReset: function(){
let data = { "name": "" };
this.$emit("reset", data);
}
}
}
After that, you can use my-form component as below:
<my-form :reset="formHasReset" #submit="onFormSubmit" #reset="onFormReset">
<input class="col-12" type="text" name="name">
<input class="col-12" type="text" name="username">
<input class="col-12" type="password" name="password">
<input class="col-12" type="email" name="email">
</my-form>
And the javascript is:
data(){
formHasReset: true
},
methods: {
onFormSubmit: function(data){
console.log(data.name); //Should give you 'dummy data'
},
onFormReset: function(data){
console.log(data.name); //Should give you ''
}
}
I hope it is clear now for you :).

how to set value form input vue js from json

please have a problem here. I want to display the value from the input form: name and position. but the data is in the form of json.
{"id":5,"name":"the name","pos":"the position"}
This is template html vue js
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
Edit <b>{{name}}</b>
</div>
<div class="card-body">
<form #submit="edit()" method="post" onclick="return false">
<div class="form-group">
<label for="">Name</label>
<input v-model="input.nameInput" type="text" value="?" autocomplete="off" class="form-control">
</div>
<div class="form-group">
<label for="">Position</label>
<input v-model="input.posInput" value="?" type="text" autocomplete="off" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Edit</button>
</form>
</div>
</div>
</div>
</div>
</div>
</template>
And this is java script of template file vue js
<script>
export default {
data(){
return{
name:'',
pos:'',
input:{
nameInput:'',
posInput:''
}
}
},
methods:{
getEmploye(){
axios.get('/employes_api/'+this.$route.params.id).then(response => {
this.name = response.data.name;
this.pos = response.data.pos;
});
},
edit(){
axios.put('/employes_api/'+this.$route.params.id, {
name: this.name,
pos: this.position,
}).then(response => {
this.$route.employe;
});
}
},
mounted(){
this.getEmploye();
}
}
</script>
Thanks for your help.
As described in your question, if the data received is
{"id":5,"name":"the name","pos":"the position"}
then you getEmploye method should be :
getEmploye(){
axios.get('/employes_api/'+this.$route.params.id).then(response => {
this.name = response.name;
this.pos = response.pos;
});
On element’s value, you may use the following to display data you have received from the api:
value=“{{name}}”
That means you are getting the value from name data.
Also, to test if that works, you may assign first a dummy data/value to name.
You don't need to make two separate variables one for the inputs and the other for the display, just keep the same variable for both, it will be automatically updated on the display and in the inputs while the user is typing, that's the beauty of Vue.
So instead of
data(){
return{
name:'',
pos:'',
input:{
nameInput:'',
posInput:''
}
}
},
Just keep
data(){
return{
name:'',
pos:''
}
},
For the template inputs use :
<input v-model="name" type="text" autocomplete="off" class="form-control">
...
<input v-model="pos" type="text" autocomplete="off" class="form-control">
The overall result should look like this :
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
Edit <b>{{name}}</b>
</div>
<div class="card-body">
<form #submit="edit()" method="post">
<div class="form-group">
<label for="">Name</label>
<input v-model="name" type="text" autocomplete="off" class="form-control">
</div>
<div class="form-group">
<label for="">Position</label>
<input v-model="position" type="text" autocomplete="off" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Edit</button>
</form>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data(){
return{
name:'',
pos:''
}
},
methods:{
getEmploye(){
axios.get('/employes_api/'+this.$route.params.id).then(response => {
this.name = response.data.name;
this.pos = response.data.pos;
});
},
edit(){
axios.put('/employes_api/'+this.$route.params.id, {
name: this.name,
pos: this.pos,
}).then(response => {
this.$route.employe;
});
}
},
created(){
this.getEmploye();
}
}
Ps : Didn't test the code, if there is any error just let me know
Use :value=“name”, e.g <input :value="name"/>.

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>

Categories

Resources