Update fields inside v-for loop using vue.js - vue.js

How can i update multiple fields inside the v-for loop using Vue.js,as i have fields which i iterate using v-for loop and want to update any field.
besides this i am able to delete and add new fields successfully.
Here what i am trying to do
Note:i can update fields with static values,but needs to update it with real values.
new Vue({
el: "#app",
data: {
users: [{
name: 'test',
phone: '1234'
}, ],
form: {
name: '',
phone: ''
},
show_link: true,
IsOn: false,
},
methods: {
addRow: function() {
this.IsOn = true
this.show_link = false
},
removeSelected(index) {
this.users.splice(index, 1);
},
saveForm() {
this.users.push({
name: this.form.name,
phone: this.form.phone
})
this.form.name = '';
this.form.phone = '';
},
updateForm(key) {
this.users[key].name = 'john doe', // should be the entered value
this.users[key].phone = '0000' // should be the entered value
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
del {
color: rgba(0, 0, 0, 0.3);
}
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<h2>Todos:</h2>
<ol>
<li v-for="(user,key) in users">
<label>
<input type="text" v-model="user.name">
<input type="text" v-model="user.phone">
<input type="button" value="Update" #click="updateForm(key)">
<input type="button" value="Delete" #click="removeSelected(key)">
</label>
</li>
</ol>
<a v-if="show_link" #click="addRow">Add Another</a>
<div v-if="IsOn">
<hr />
<input type="text" name="name" v-model="form.name">
<input type="text" name="name" v-model="form.phone">
<input type="button" value="Save" #click="saveForm">
</div>
</div>

Related

v-for: Array element and destructuring of properties

When working with an array of objects, is it possible in a v-for-loop to assign the current object to a variable and destruct its properties at the same time? Something like this:
<div v-for="(person = {name, age}, index) in persons">
Ultimately I'm looking for a way to use e.g. both the whole person object and its properties in a template.
As far as I know, you can't do both.
But, you can destructure, i.e.
<div v-for="({name, age}, index) in persons">
You could then just access the correct element with the index: persons[index].
Example:
new Vue({
el: "#app",
data: {
todos: [{
text: "Learn JavaScript",
done: false
},
{
text: "Learn Vue",
done: false
},
{
text: "Play around in JSFiddle",
done: true
},
{
text: "Build something awesome",
done: true
}
]
},
methods: {
toggle: function(index) {
this.todos[index].done = !this.todos[index].done
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
del {
color: rgba(0, 0, 0, 0.3);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Todos:</h2>
<ol>
<li v-for="({text, done}, i) in todos">
<label>
<input type="checkbox"
v-on:change="toggle(i)"
v-bind:checked="done">
<del v-if="done">
{{ text }}
</del>
<span v-else>
{{ text }}
</span>
{{todos[i]}}
</label>
</li>
</ol>
</div>

How to get radio button value from multiple radio button with same v-model name?

How can I get the value from my multiple radio button by same v-model name?
I expect I can check only one button for each student and put its value into the info[] array.
new Vue({
el: "#app",
data: {
info: [],
student_id: [
{ name: 'Andrew', student_id: '52346' },
{ name: 'Mathew', student_id: '86975' },
{ name: 'Max', student_id: '78654' },
{ name: 'Jhon', student_id: '36589' },
{ name: 'Flam', student_id: '74859' },
{ name: 'Meli', student_id: '62398' }
]
},
methods: {
submit() {
console.log(this.info)
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
del {
color: rgba(0, 0, 0, 0.3);
}
<div id="app">
<v-container>
<form #submit.prevent="submit">
<div v-for="(id,i) in student_id" class="pa-3">
<span class="blue--text">{{id.name}}</span>
<br />
<input type="radio" :name="`${id.name}`" v-model="info" :value="`${id.student_id}-P`" /> Present
<input type="radio" v-model="info" :name="`${id.name}`" :value="`${id.student_id}-A`" /> Absent
<input type="radio" v-model="info" :name="`${id.name}`" :value="`${id.student_id}-L`" /> Late
<hr />
</div>
<v-btn color="success" type="submit">Submit</v-btn>
</form>
</v-container>
</div>
View on JSFiddle
new Vue({
el: "#app",
data: {
student_id: [{
name: 'Andrew',
student_id: '52346',
value: ''
},
{
name: 'Mathew',
student_id: '86975',
value: ''
},
{
name: 'Max',
student_id: '78654',
value: ''
},
{
name: 'Jhon',
student_id: '36589',
value: ''
},
{
name: 'Flam',
student_id: '74859',
value: ''
},
{
name: 'Meli',
student_id: '62398',
value: ''
}
]
},
computed: {
info() {
return this.student_id.map(item => item.value)
}
},
methods: {
submit() {
console.log(this.info)
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
del {
color: rgba(0, 0, 0, 0.3);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app">
<v-container>
{{info}}
<form #submit.prevent="submit">
<div v-for="(id,i) in student_id" class="pa-3">
<span class="blue--text">{{id.name}}</span>
<br />
<input type="radio" :name="`${id.name}`" v-model="id.value" :value="`${id.student_id}-P`" /> Present
<input type="radio" v-model="id.value" :name="`${id.name}`" :value="`${id.student_id}-A`" /> Absent
<input type="radio" v-model="id.value" :name="`${id.name}`" :value="`${id.student_id}-L`" /> Late
<hr />
</div>
<v-btn color="success" type="submit">Submit</v-btn>
</form>
</v-container>
</div>
Put the value of each radio group in the object in the array, and then calculate the selected value by computed.

Toggle form inside v-for using vue.js

How can i toggle form inside v-for loop,I have a form inside v-for which i want to display (toggle) on click.
But when i click all the form inside the v-for gets toggled.
Secondly is it better approach to keep the form inside the loop,when have large amount of data inside loop or load it as a separate component.
This is what i am trying to do.
new Vue({
el: "#app",
data: {
todos: [{
text: "Learn JavaScript"
},
{
text: "Learn Vue"
},
{
text: "Play around in JSFiddle"
},
{
text: "Build something awesome"
}
],
show: ''
},
methods: {
toggle: function(todo) {
this.show = !this.show
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
del {
color: rgba(0, 0, 0, 0.3);
}
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<h2>Todos:</h2>
<ol>
<li v-for="(todo,key) in todos">
<p>
{{ key+1 }} - {{ todo.text}} <span #click="toggle(todo)"><b>Contact</b></span>
<div v-if="show">
<hr />
<p>
<label>Message</label>
<input type="text">
</p>
<hr />
</div>
</p>
</li>
</ol>
</div>
There is only 1 reactive variable show. Setting it to true while all form is using v-if="show", will show everything.
You can set show to something that each form uniquely have. For example, its text, and perform a v-if using its text.
demo: https://jsfiddle.net/jacobgoh101/umaszo9c/
change v-if="show" to v-if="show === todo.text"
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<h2>Todos:</h2>
<ol>
<li v-for="(todo,key) in todos">
<p>
{{ key+1 }} - {{ todo.text}} <span #click="toggle(todo)"><b>Contact</b></span>
<div v-if="show === todo.text">
<hr />
<p>
<label>Message</label>
<input type="text">
</p>
<hr />
</div>
</p>
</li>
</ol>
</div>
change toggle method
new Vue({
el: "#app",
data: {
todos: [{
text: "Learn JavaScript"
},
{
text: "Learn Vue"
},
{
text: "Play around in JSFiddle"
},
{
text: "Build something awesome"
}
],
show: ''
},
methods: {
toggle: function(todo) {
if (this.show === todo.text)
this.show = false
else
this.show = todo.text
}
}
})
property "show" should be a prop of todo,not prop of data
new Vue({
el: "#app",
data: {
todos: [{
text: "Learn JavaScript"
},
{
text: "Learn Vue"
},
{
text: "Play around in JSFiddle"
},
{
text: "Build something awesome"
}
].map(o=>({...o,show:false}))
},
methods: {
toggle: function(todo) {
todo.show = !todo.show
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
del {
color: rgba(0, 0, 0, 0.3);
}
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<h2>Todos:</h2>
<ol>
<li v-for="(todo,key) in todos">
<p>
{{ key+1 }} - {{ todo.text}} <span #click="toggle(todo)"><b>Contact</b></span>
<div v-if="todo.show">
<hr />
<p>
<label>Message</label>
<input type="text">
</p>
<hr />
</div>
</p>
</li>
</ol>
</div>

Assing uploaded file value to input field multiple times using vue.js

Assign filename to input field on upload and then show success message working fine,but when i try to delete file and upload again it's not working!
new Vue({
el: "#app",
data() {
return {
form: {
message: '',
fileurl: ''
},
loading: false
}
},
methods: {
uploadImage(event) {
this.form.fileurl = 'uploaded!'
},
deleteFile(furl) {
this.form.fileurl = ''
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
span {
color: red;
}
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<h3>
File Upload / remove Demo
</h3>
<hr />
<div class="custom-file attach_file" v-show="!form.fileurl">
<input type="file" id="file" name="file" #change="uploadImage($event)">
<input type="text" v-model="form.fileurl">
</div>
<p v-if="form.fileurl"> {{ form.fileurl }} <span #click="deleteFile(form.fileurl)">Delete</span></p>
</div>
I am not getting any console error as well.
This is what i have tried so far.
Can you guys please have a look at this!
The problem is that #change is not trigger when you choose the same file. The simplest solution is reset value of input when you click delete
this.$refs.fileToUpload.value = '';
new Vue({
el: "#app",
data() {
return {
form: {
message: '',
fileurl: ''
},
loading: false
}
},
methods: {
uploadImage(event) {
this.form.fileurl = 'uploaded!'
},
deleteFile(furl) {
this.form.fileurl = ''
this.$refs.fileToUpload.value = '';
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
span {
color: red;
}
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<h3>
File Upload / remove Demo
</h3>
<hr />
<div class="custom-file attach_file" v-show="!form.fileurl">
<input type="file" id="file" name="file" class="custom-file-input" #change="uploadImage($event)" ref="fileToUpload">
<input type="text" v-model="form.fileurl">
</div>
<p v-if="form.fileurl"> {{ form.fileurl }} <span #click="deleteFile(form.fileurl)">Delete</span></p>
</div>
You need to clear you input field first.
Update your upload method with this.
uploadImage(event) {
this.form.fileurl = 'uploaded!'
this.success = false
this.$nextTick(() => {
this.success = true
})
Have a look at this working demo
https://jsfiddle.net/asimshahzad/8c9pcfys/

Vue.js 2.0 data binding issue - one data field's change will trigger the other data fields' filter

Following is the code, I define a my data in Vue as below:
{
result: {
name: 'user A',
age: 20,
male: true
},
showDetails: true
}
There are several filter/computed/methods in the view will do the result formatting.
The problem is even I just change the value of the showDetailds, the methods and filters defined for the result will be triggered as well.
May I know any issue in my code ? Or it's the natural of Vue.js (I don't believe.) ?
function countTheCall(key) {
let counter = document.getElementById(key)
if (!counter) {
let container = document.getElementById('statList')
var item = document.createElement('li')
item.innerHTML = `${key}: <span id='${key}'>0</span>`
container.appendChild(item)
counter = document.getElementById(key)
}
counter.innerText = _.parseInt(counter.innerText) + 1
}
var vm = new Vue({
el: '#app',
data() {
return {
result: {
name: 'user A',
age: 20,
male: true
},
showDetails: true
}
},
methods: {
countTheCall: function(key) {
let counter = document.getElementById(key)
counter.innerText = _.parseInt(counter.innerText) + 1
},
trimValue: function(value) {
console.log('Invoke method - trimValue.')
countTheCall('methodCalls of trimValue')
return _.trim(value)
},
getValFromResult: function(key) {
console.log('Invoke method - getValFromResult.')
countTheCall('methodCalls of getValFromResult')
return _.get(this.result, key, 'null')
}
},
computed: {
displayName: function() {
console.log('Invoke computed value - computedVal.')
countTheCall('computedCalls of displayName')
return `${this.result.name} (${this.result.age})`
}
},
filters: {
convertString: function(val) {
countTheCall('filterCalls of convertString')
return _.upperFirst(val)
},
getValFromObject: function(obj, key) {
console.log(`[filter] getValue From Object by ${key}`)
countTheCall('filterCalls of getValFromObject')
return _.get(obj, key, 'null')
},
convertDateString: function(datestr, format = 'MMM DD (ddd), YYYY') {
console.log(`[filter] convertDateString ${datestr}`)
countTheCall('filterCalls of convertDateString')
let m = moment(datestr)
let formattedStr = ''
if (m.isValid()) {
formattedStr = m.format(format)
}
return formattedStr
}
}
})
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
label {
font-style: italic;
color: black;
}
span {
font-weight: bold;
color: darkblue;
}
.callStat {
float: right;
width: 400px;
border: solid darkgrey 2px;
padding: 5px;
margin-right: 40px;
}
<body>
<script type="text/javascript" src="//cdn.bootcss.com/vue/2.2.4/vue.min.js"></script>
<script type="text/javascript" src="//cdn.bootcss.com/moment.js/2.17.1/moment-with-locales.min.js"></script>
<script type="text/javascript" src="//cdn.bootcss.com/lodash.js/4.17.4/lodash.min.js"></script>
<div class="callStat">
<h4>The Stat. of Calls</h4>
<ul id="statList"></ul>
</div>
<div id="app">
<h2>User Profile</h2>
<div>
<label>User Name:</label>
<input type="text" v-model="result.name"></input>
</div>
<div>
<label>Show Details:</label>
<input type="checkbox" id="showDetails" v-model="showDetails"></input>
<label for="showDetails">show detail section?</label>
</div>
<hr/>
<div>
<label>User Name:</label>
<ul>
<li>result.name: <span>{{trimValue(result.name)}}</span></li>
<li>result.unknownFiled: <span>{{result.unknownFiled}}</span></li>
<li>getValFromResult('name'): <span>{{ getValFromResult('name')}} </span></li>
<li>getValFromResult('unknownField'): <span>{{ getValFromResult('unknownField')}} </span></li>
<li>computed Display Name : <span>{{ displayName }} </span></li>
<li>convertString by filter : <span>{{ result.name | convertString }} </span></li>
<li>user birthDay: <span>{{ result.birthDay | convertDateString}}</span></li>
</ul>
</div>
</div>
</body>
This is natural to Vue.
Methods & Filters run on every DOM re-render.
This is why it's best to use Computed whenever possible - these re-run only on change of connected properties.