run loop backward in template in vuejs - vue.js

<template>
<li v-for="r in recent">
{{r}}
</li>
</template>
recent is an array .
I don't want to list contents of recent from 0 to n-1 .
Instead i want to list it from n-1 to 0.
I tried ->
<template>
<li v-for="r=recent.length-1 ; r>=0 ; r--">
{{r}}
</li>
</template>
But, it didn't work.

Solution 1: Reverse array directly in template
You can actually reverse the array directly in your template before iterating through it, using recent.slice().reverse(). Using .slice() is necessary because this.recent is actually not an array per se. However, I do not prefer this method because it means placing logic in your template.
<template>
<li v-for="r in recent.slice().reverse()">
{{r}}
</li>
</template>
new Vue({
el: '#list',
data: {
recent: [
'Lorem',
'ipsum',
'dolor',
'sit',
'amet'
]
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<ul id="list">
<li v-for="r in recent.slice().reverse()">
{{ r }}
</li>
</ul>
Solution 2: Use a computed property
As what #vbranden has said, you can simply reverse an array in a method and use it in v-for. This is my preferred method.
new Vue({
el: '#list',
data: {
recent: [
'Lorem',
'ipsum',
'dolor',
'sit',
'amet'
]
},
computed: {
recentReversed: function() {
return this.recent.reverse();
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<ul id="list">
<li v-for="r in recentReversed">
{{ r }}
</li>
</ul>

You should use Array.prototype.reverse()
Source : link
In your computed
export default Vue.extend({
name: 'mainActivity',
data (){
return{
stuff: ['a', 'b', 'c', 'd']
}
},
computed:{
reverseArray(){return this.stuff.reverse()}
},
created(){}
})
HTML
<template>
<li v-for="r in reverseArray">
{{r}}
</li>
</template>

There is no for-loop form of v-for. There is a range form, which you can use to get the effect you want (with a little simple math).
You could do the same thing with a computed, as vbranden noted in his comment.
new Vue({
el: '#app',
data: {
stuff: ['a', 'b', 'c', 'd']
},
computed: {
stuffIndexCountdown() {
return this.stuff.map((_, i) => i).reverse();
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="app">
<div v-for="i in stuff.length">
{{stuff.length - i}}
</div>
<hr>
<div v-for="i in stuffIndexCountdown">
{{i}}
</div>
</div>

Related

VueJS renders variable twice in loop

When I press some key in editable <li> it shows this content twice. Out of this v-for loop, it shows only once. So in this array is for example ['a'] but in <li> it shows 'aa'
new Vue({
el: '#app',
data: {
component: {
items: ['']
}
},
methods: {
onKeydown(e, index) {
if(e.key === 'Enter') {
e.preventDefault()
this.component.items.push('')
}
},
onInput(e, index, item) {
this.component.items.splice(index, 1, e.target.innerHTML)
}
}
});
<div id="app">
<ul>
<li contenteditable="true"
v-for="(item, index) in component.items"
:key="index"
#keydown="onKeydown($event, index)"
#input="onInput($event, index, item)"
>{{ item }}</li>
</ul>
{{ component.items }}
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

How to get the value with v-select, options loaded from ajax using slot templates

I am trying to get the selected value to update in my vue component, but it doesn't change and stays empty instead, i can select things but i can't do anything with it.
I have tried adding :value to the v-select component, but it just doesn't update the value whenever i select something.
Since i am still trying this with the example from their documentation, i made a fork on codepen here: https://codepen.io/andyftp/pen/GweKpP so you can try it out.
Anyone can help me here?
HTML:
<div id="app">
<h1>Vue Select - Ajax</h1>
<v-select label="name"
:filterable="false"
:options="options"
:selected="selected"
#search="onSearch"
><template slot="no-options">
type to search GitHub repositories..
</template>
<template slot="option" slot-scope="option">
<div class="d-center">
<img :src='option.owner.avatar_url'/>
{{ option.full_name }}
</div>
</template>
<template slot="selected-option" scope="option">
<div class="selected d-center">
<img :src='option.owner.avatar_url'/>
{{ option.full_name }}
</div>
</template>
</v-select>
Selected: {{ selected }}
</div>
JS:
Vue.component("v-select", VueSelect.VueSelect);
new Vue({
el: "#app",
data: {
selected: null, // this needs to be filled with the selected value (id or object), but it stays empty
options: []
},
methods: {
onSearch(search, loading) {
loading(true);
this.search(loading, search, this);
},
search: _.debounce((loading, search, vm) => {
fetch(
`https://api.github.com/search/repositories?q=${escape(search)}`
).then(res => {
res.json().then(json => (vm.options = json.items));
loading(false);
});
}, 350)
}
});

vuejs auto-filter out an array marked "Bar"

I am new vuejs but learning a lot. I Have an array of items that renders to a list perfectly fine. I do want to not display anything marked Bar? I have tried !Bar but it does not work. Whats the correct way to do this?
var app = new Vue({
el: "#demo",
data: {
items: [{
childMsg: 'Foo'
}, {
childMsg: 'Bar'
}]
}
});
<script src="https://unpkg.com/vue"></script>
<div id="demo">
<ul v-for="item in items">
<li>{{item.childMsg}}</li>
</ul>
</div>
As usual, there are several approaches. One most straightforward is to exclude the item directly within v-for element template, like this:
<li v-if="item.childMsg !== 'Bar'">{{item.childMsg}}</li>
An alternative would be creating a computed property: array of items that do not match the pattern. Then you can rebase your v-for onto that property. Here's how it can be done:
var app = new Vue({
el: "#demo",
data: {
exclude: '',
items: [{
childMsg: 'Foo'
}, {
childMsg: 'Bar'
}]
},
computed: {
filteredItems() {
return this.items.filter(x => x.childMsg !== this.exclude);
}
}
});
<script src="https://unpkg.com/vue"></script>
<div id="demo">
<label>Exclude word... <input type="text" v-model="exclude" /></label>
<ul v-for="item in filteredItems">
<li>{{item.childMsg}}</li>
</ul>
</div>

VueJS: Why v-model does not work with a vuejs filter

Why v-model does not work with a filter getUppercase in <input v-model="filterText | getUppercase">
HTML
<template>
<div class="wrapper">
Check if fruit exist: <input v-model="filterText | getUppercase">
<ul v-for="fruit in filteredFruits">
<li> {{ fruit }} </li>
</ul>
</div>
</template>
VueJS
export default {
name: "filterText",
data() {
return {
msg: "Welcome to Your Vue.js App",
filterText: "",
fruits: ["Apple", "Banana", "Orange", "PineApple", 'Pina Colada']
};
},
computed: {
filteredFruits: function() {
var vm = this;
return vm.fruits.filter(function(item) {
return item.match(vm.filterText)
});
}
},
filters: {
getUppercase: function(obj) {
return this.obj.toUpperCase();
}
}
};
I can see what you are trying to do, however, because of the two way binding when using v-model, it will be better to just apply the getUppercase filter when displaying.
Your template would be something like this:
<template>
<div class="wrapper">
Check if fruit exist: <input v-model="filterText">
<ul v-for="fruit in filteredFruits">
<li> {{ fruit | getUppercase}} </li>
</ul>
</div>
</template>
But if you still wish to transform the filterText model value, you can use a directive. In that case, your VueJS code will be something like :
Vue.directive('getUppercase', {
twoWay: true, // this transformation applies back to the filterText
bind: function () {
var self = this;
self.handler = function () {
self.set(self.el.value.toUpperCase());
}
self.el.addEventListener('input', self.handler);
},
unbind: function () {
this.el.removeEventListener('input', this.handler);
}
});
Now use this directive in your template like :
<input v-model="filterText" v-get-uppercase="filterText">
It will do the same thing as <input v-model="filterText | getUppercase">
Two ways filters are replaced in vue.js please read the docs for more information.It is good to know.
However,as i understood you want to implement a search in array.See it in action here, or take a look below
<div id="app">
Check if fruit exist: <input v-model="filterText">
<ul v-for="fruit in filteredFruits">
<li> {{ fruit }} </li>
</ul>
</div>
new Vue({
el: "#app",
data: {
filterText: "",
fruits: ["Apple", "Banana", "Orange", "PineApple", 'Pina Colada']
},
computed: {
filteredFruits() {
return this.fruits.filter(item => item.toLowerCase().match(this.filterText.toLowerCase()))
}
}
})

VueJS 2 Directives insert event

I'm new VueJS Student, and i was trying to do a directive, and i stopped because i dont know why i can't get the element. What's am i doing wrong? I just want to get the el element.
Here is a JSFiddle or the code below.
HTML
<div class="container" id="vue-app">
<ul>
<li v-test v-for="item in itens">
{{item.name}}
</li>
</ul>
<span id="directiveLog"></span>
</div>
JS
Vue.directive('test', {
inserted: function (el) {
document.querySelector('#directiveLog').innerHTML = el;
}
})
new Vue({
el: '#vue-app',
data: {
itens:[
{name: "hello"},
{name: "fun"},
{name: "world"}
]
}
});
Parameter 'el' in function inserted(el) {...} - it is your element where v-test is inserted.
Vue.directive('test', {
inserted: function (el) {
document.querySelector('#directiveLog').innerHTML = el.innerHTML;
}
})
new Vue({
el: '#vue-app',
data: {
itens:[
{name: "hello"},
{name: "fun"},
{name: "world"}
]
}
});
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div v-test class="container" id="vue-app">
<ul>
<li v-for="item in itens">
{{item.name}}
</li>
</ul>
<span id="directiveLog"></span>
</div>