Vue.js v-for element from $refs broken in watch function - javascript

With Vue.js 2.5.22 and FireFox 65.0. What am I missing?
https://jsfiddle.net/r083hqgv/2/
A v-for element identified by a :ref="x" attribute doesn't work as expected in a watch function. I've also tried using :id="x" & getElementById(), and calling setTimeout(..., 200) within $nextTick().
Code from the above fiddle:
<div id="app" style="position:relative">
<h2>last element top: {{offset+''}}</h2>
<button #click="add()">Add & get top</button>
<ol>
<li v-for="a in list" :key="'r.'+a">
<a #click.stop.prevent="get($event.target)" href="#"
:ref="'r.'+a">get top {{'r.'+a}}</a>
</li>
</ol>
</div>
new Vue({
el: "#app",
data: {
offset: 0,
last: 'unset',
list: [],
},
methods: {
add: function() {
this.last = 'r.'+ this.list.push(this.list.length+1);
this.list = this.list.slice();
},
get: function(iEl) {
this.offset = iEl.offsetTop;
iEl.style = 'font-style:italic';
}
},
watch: {
list: function() {
this.$nextTick(function() {
var aEl = this.$refs[this.last];
if (aEl) this.get(aEl);
});
}
}
})

As referenced by the documentation ($refs), this.$refs["..."] returns an array when v-for is used. Therefore, change
if (aEl) this.get(aEl);
to
if (aEl) this.get(aEl[0]);
Everything will work (I already tested it on your jsfiddle).

Related

Vue pass data into array specific item name

Hey I am really new to Vue and for this project I was trying to add data inside array using .push() . When I push data inside totalPlayers its suppose to get data as totalPlayers[{data:[0,1,2,3]}] but it currently saves data as totalPlayers[{data: [] }, 0, 1, 2, 3]. Is there a way to fix this? Here is my code below
JsFiddle = https://jsfiddle.net/ujjumaki/xv2homt8/24/
Method
new Vue({
el: "#app",
data: {
totalPlayers:[{
data:[],
}],
playerList:4,
},
methods: {
buttonClicked(){
for (var i = 0; i < this.playerList; i++) {
console.log('i was '+i);
this.totalPlayers.push(i);
console.log(this.totalPlayers);
}
}
}
})
View
<div id="app">
<button #click="buttonClicked()">
Click Me
</button>
</div>
data is array in first element of totalPlayers array, so try totalPlayers[0].data.push:
new Vue({
el: "#app",
data: {
totalPlayers:[{
data:[],
}],
playerList:4,
},
methods: {
buttonClicked(){
for (var i = 0; i < this.playerList; i++) {
console.log('i was '+i);
this.totalPlayers[0].data.push(i);
console.log(this.totalPlayers);
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button #click="buttonClicked()">
Click Me
</button>
</div>
Just use this to push: this.totalPlayers[0].data.push(i);
since totalPlayers is an array and you want to add to it's first element that is an object
jsfiddle

Pass click action using array and v-for (Vue.js)

I am trying to pass through a v-for the text and the #click action of each li. For the text I know how to do it...but for the click action?enter code here
Each item of the array menuOptions (which is in the 'data' part of my Vue component) is structured like this :
{name: "firstOption",action: "console.log('first option called')"}
The first parameter is the name of the option, the
<ul>
<li v-for="option in menuOptions" #click="option.action">{{option.name}}</li>
</ul>
Do you have some ideas? (I guess that's maybe a pure JS question, but maybe there are possibilities to do it Vue too?)
Pass a function expression to the action property, instead of a "stringified" function.
{
name: 'firstOption',
action: function() {console.log('first option called'}
}
var app = new Vue({
el: '#app',
data: {
menuOptions: [{
action: function() {
console.log('foo')
},
name: 'foo'
}, {
action: function() {
console.log('bar')
},
name: 'bar'
}],
}
})
<script src="https://unpkg.com/vue"></script>
<div id='app'>
<ul>
<li v-for="option in menuOptions" #click="option.action">{{option.name}}</li>
</ul>
</div>

Vue Js binding 2 values to a tag href

I'm beginner on Vue js. I'm facing an issue where I have to update two values while rendering.
<ul class="category-list">
<li v-for="category in categories">
<a v-bind:href="location/category.slug/all" v-text="category.name"></a>
</li>
</ul>
My javascript file
new Vue({
el : '#example',
data : {
location: 'new-york',
categories: [],
},
mounted() {
axios.get('parent-categories').then((response) => {
this.categories = response.data;
});
},
});
Ajax Response
[{"name":"Default Category","slug":"default-category"},{"name":"Main Category","slug":"main-category"}]
Here I wanted to build url structure like location/category-slug/all ie,
http://myapp.com/new-york/default-category/all
How to achieve this?
Found out how to handle this situation after a long struggle. All I have to do is to create a method that generates URL for me.
JS
new Vue({
el : '#example',
data : {
location: 'new-york',
categories: [],
},
methods: {
slug: function (category) {
return this.location+'/'+category.slug+'/all';
}
},
mounted() {
axios.get('parent-categories').then((response) => {
this.categories = response.data;
});
},
});
Html
<div id="example">
<h3>Services</h3>
<ul class="category-list">
<li v-for="category in categories">
<a :href="slug(category)" v-text="category.name"></a>
</li>
</ul>
</div>

v-for through an object in vue.js

I have a Teams object, which has a record of all teams and can also count and create them. I store all teams as an object, so I can write Teams.all["Team 1"] to select a team with a name of "Team 1".
Teams.js
var Teams = {
all: {},
create: function(teamName) {
var key = 'Team ' + this.count();
this.all[key] = {
'name': teamName,
'score': 0
};
},
count: function() {
var total = 0;
for(var team in this.all){
if(this.all.hasOwnProperty(team)){
total ++;
}
}
return total;
}
}
Now in vue I'd like to loop through this.
main.js
var vueApp = new Vue({
el: '#app',
data: {
'Teams' : Teams
},
methods : {
createTeam : function(){
Teams.create('Team ' + (Teams.count() + 1));
}
}
});
And then this doesn't work (obviously):
index.html
<div id="app">
<ul>
<li v-for="team in Teams.all">{{ team.name }}</li>
</ul>
<button #click="createTeam">Create team</button>
</div>
So my next guess was to go like this:
index.html
<div id="app">
<ul>
<li v-for="team in Teams.all">{{ Teams.all[team].name }}</li>
</ul>
<button #click="createTeam">Create team</button>
</div>
But that doesn't work either. Is there a way to loop through the properties of an object in Vue?
http://codepen.io/EightArmsHQ/pen/wzPKxA
Your Teams state is not reactive because you are adding object keys to it... Read this docs here: http://rc.vuejs.org/guide/reactivity.html#Change-Detection-Caveats.
Use this.$set(this.someObject, 'b', 2) if you want to add properties to your state object or those won't be reactive and trigger view update.
Also not sure why you complicate so much :). Try this:
var vueApp = new Vue({
el: '#app',
data: {
teams: []
},
methods: {
addTeam: function() {
this.teams.push({
name: 'Team ' + this.teams.length,
score: 0
})
}
}
});
<div id="app">
<ul>
<li v-for="team in teams">
{{ team.name }}
</li>
</ul>
<button #click="addTeam">Create team</button>
</div>
Demo here: http://codepen.io/anon/pen/qaVbym

Vue.js: How to read $index inside computed function?

I have list of links:
<ul id="menu">
<li v-for="item in items">
<a href v-bind:href=link>{{item.message}}</a>
</li>
</ul>
var example1 = new Vue({
el: '#menu',
data: {
items: [
{ message: 'Link1' },
{ message: 'Link2' }
]
},
computed: {
link: function() {
return f($index) // how do I access current array index ??
}
}
})
I can achieve the desired result by using mustache markup in a href attribute but it must be possible to access this $index variable from within a computed function?
You can't.
This is what methods are for:
<a href v-bind:href="link($index)">{{item.message}}</a>
methods: {
link: function(index) {
return f(index)
}
}

Categories

Resources