Vue Filtering and Pagination - javascript

How can you render a certain number of array objects based on a selected number say 10 or 15 or 25 in Vue pagination ? I have tried rendering 10 items per page and it's working well.

You can create a computed property that slices your array, and use this computed property when iterating the array with v-for:
var app = new Vue({
el: '#app',
data: {
items: [
{ id: 1, name: 'Foo' },
{ id: 2, name: 'Bar' },
{ id: 3, name: 'Baz' }
],
amountOfItemsShown: 2,
},
computed: {
slicedItems() {
return this.items.slice(0, this.amountOfItemsShown);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<p>Amount of items shown: <input type="range" :min="1" :max="3" v-model="amountOfItemsShown"> <strong>{{ amountOfItemsShown }}</strong></p>
<div v-for="item in slicedItems" :key="item.id">
{{ item.name }}
</div>
</div>

Related

Vue 3 How to dynamically load data from server and show in a v-for loop

I want to dynamically showing data from from the database in a v-for loop. However, if I try to push the new data into the array, they are displayed correctly in a console.log(), but nothing changes in the template.
I made a simplified representation of this in Codepen:
<template>
<ul v-for="number in numbers">
<li>{{ number.num }} : {{ number.text }}</li>
</ul>
{{ numbers }}
</template>
<script setup>
let numbers = [
{ num: 1, text: "One" },
{ num: 2, text: "Two" },
{ num: 3, text: "Three" }
];
// simulate server
setTimeout(() => {
numbers.push({ num: 4, text: "Four" });
console.log(numbers); // returns the array correct
}, 3000);
</script>
Link to the Snippet: https://codepen.io/Tenarius/pen/QWBLOJZ
Can someone help me?
When using vue, the variables must be reactive to make changes on data. It's also accessible on .value. Read more on this https://vuejs.org/guide/essentials/reactivity-fundamentals.html and accessing the refs https://vuejs.org/guide/essentials/template-refs.html#accessing-the-refs
Here's a sample working code
<template>
<ul v-for="number in numbers">
<li>{{ number.num }} : {{ number.text }}</li>
</ul>
{{ numbers }}
</template>
<script setup>
import { ref } from 'vue'
let numbers = ref([
{ num: 1, text: "One" },
{ num: 2, text: "Two" },
{ num: 3, text: "Three" }
]);
// simulate server
setTimeout(() => {
numbers.value.push({ num: 4, text: "Four" });
console.log(numbers); // returns the array correct
}, 3000);
</script>

Loop throuth a filtered list in vue.js with parameter

How to loop in vue.js through a filtered list with an input parameter given?
Pls. take into consideration that filtering like <li v-for="x in todos_filtered" v-if="x.person == 'Mike'"> should be avoided with many records.
Here the code which returns an empty list instead of 2 elements.
<html>
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.14/dist/vue.js"></script>
<body>
<div id="app">
<ul>
<li v-for="x in todos_filtered('Mike')">
{{ x.text }}
</li>
</ul>
</div>
<script>
myObject = new Vue({
el: '#app',
data: {
todos: [
{ person: 'Mike', text: 'Learn JavaScript' },
{ person: 'Luke', text: 'Learn Vue.js' },
{ person: 'Mike', text: 'Build Something Awesome' }
]
},
computed: {
todos_filtered(person) {
return this.todos.filter((x) => x.person === person);
}
},
})
</script>
</body>
</html>
The computed property should return a function that take the person as parameter:
computed: {
todos_filtered() {
return (person)=> this.todos.filter((x) => x.person === person);
}
},

Vuejs draggable sorted list

I'm using Vue.Draggable plugin to implement a draggable list. I'm passing a sorted computed property, like the following:
data(){
return {
paymentMethods: [
{ name: 'stripe', Dindex: 0, state: 2 },
{ name: 'paypal', Dindex: 1 , state: 1 },
{ name: '2checkout', Dindex: 2, state: 4 },
{ name: 'cod', Dindex: 3, state: 3 }
],
}
},
computed: {
payments() {
return _.sortBy(this.paymentMethods, 'state');
},
}
Draggable list:
<draggable :list="payments" class="payment-methods" tag="ul" #start="drag=true" #end="drag=false" #change="indexChanged">
<li v-for="(method, index) in payments" :key="index">
<!-- list data -->
</li>
</draggable>
The problem here is the draggable list never works because i'm forcing the list sorting (using lodash _.sortBy), the question is how i can sort inside a draggable list.
While it is a computed value the list will sorted again when you drag it. I think the best thing to do is sort it when mounted:(So only initially)
data() {
return {
payments: []
paymentMethods: [
{ name: 'stripe', Dindex: 0, state: 2 },
{ name: 'paypal', Dindex: 1 , state: 1 },
{ name: '2checkout', Dindex: 2, state: 4 },
{ name: 'cod', Dindex: 3, state: 3 }
],
}
}
mounted() {
payments = _.sortBy(this.paymentMethods, 'state');
}
I know this is kind of old but I've also tried Googling for a solution and couldn't find any. A few minutes later I came up with this:
// <template />
<draggable
class="drag-wrapper selected-cols"
v-bind="dragOptions"
...other props
#change="colChange"
>
<div v-for="(col, i) in availableColumns" :key="col.name + '-' + i">
<div class="drag-area">
{{ col.label }}
</div>
</div>
</draggable>
// <scripts />
methods: {
colChange(e) {
this.availableColumns.sort((a, b) =>
a.label.localeCompare(b.label));
},
},
So instead of using a computed for sorting, I just do the sorting in the #change listener since that is being called AFTER vuedraggable is done sorting.

How to access to item from HTML Node [Vue.js]

I have:
Vue app data:
data: function() {
return {
items: [
{id: 1, text: 'one', other_data: {}},
{id: 2, text: 'two', other_data: {}},
{id: 3, text: 'three', other_data: {}}
]
}
}
Template:
<div v-for="item in items" id="my_items">
<span>{{ item.text }}</span>
</div>
And i need to access from one item by external JS code like next:
let item_node = document.getElementById('my_items').children[1]; // get 2nd child node of #my_items
item_node.__vuedata__ // must be a 2nd item from items in Vue data. {id: 2, text: 'two'...
How to do like this?
Vue recommends to use ref over ID and classes for DOM references. We use ref as a replacement for id. Since it is used on top of the v-for directive, all child elements are now referenced as an array of the ref. So every span will now be hello[0] - hello[n] The mounted code outputs the item.text for first child as it uses 0.
I added a click listener, every time you click the element, the value of item is passed to the method. Here you can extract all values and do whatever manipulation you require. Hope this is what you are looking for.
<template>
<div id="app">
<div v-for="item in items" :key="item.id" ref='hello' #click="logItem(item)">
<span>{{ item.text }}</span>
</div>
</div>
</template>
<script>
export default {
name: "App",
data: function() {
return {
items: [
{id: 1, text: 'one', other_data: {}},
{id: 2, text: 'two', other_data: {}},
{id: 3, text: 'three', other_data: {}}
]
}
},
methods: {
logItem: (item) => console.log(item)
},
mounted: function() {
console.log(this.$refs.hello[0].innerText)
}
};
</script>

Multiple select Vue.js and computed property

I'm using Vue.js 2.0 and the Element UI library.
I want to use a multiple select to attribute some roles to my users.
The list of all roles available is received and assigned to availableRoles. Since it is an array of object and the v-model accepts only an array with value, I need to extract the id of the roles trough the computed property computedRoles.
The current roles of my user are received and assigned to userRoles: [{'id':1, 'name':'Admin'}, {'id':3, 'name':'User'}].
computedRoles is then equals to [1,3]
The preselection of the select is fine but I can't change anything (add or remove option from the select)
What is wrong and how to fix it?
http://jsfiddle.net/3ra1jscx/3/
<div id="app">
<template>
<el-select v-model="computedRoles" multiple placeholder="Select">
<el-option v-for="item in availableRoles" :label="item.name" :value="item.id">
</el-option>
</el-select>
</template>
</div>
var Main = {
data() {
return {
availableRoles: [{
id: 1,
name: 'Admin'
}, {
id: 2,
name: 'Power User'
}, {
id: 3,
name: 'User'
}],
userRoles: [{'id':1, 'name':'Admin'}, {'id':3, 'name':'User'}]
}
},
computed : {
computedRoles () {
return this.userRoles.map(role => role.id)
}
}
}
I agree mostly with #wostex answer, but he doesn't give you the userRoles property back. Essentially you should swap computedRoles and userRoles. userRoles becomes a computed property and computedRoles is a data property. In my update, I changed the name of computedRoles to selectedRoles.
var Main = {
data() {
return {
availableRoles: [{
id: 1,
name: 'Admin'
}, {
id: 2,
name: 'Power User'
}, {
id: 3,
name: 'User'
}],
selectedRoles:[1,2]
}
},
computed : {
userRoles(){
return this.availableRoles.reduce((selected, role) => {
if (this.selectedRoles.includes(role.id))
selected.push(role);
return selected;
}, [])
}
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
And here is the fiddle.
Check the solution: jsfiddle
The caveat here is that computed properties are getters mainly. You can define setter for computed property, but my approach is more vue-like in my opinion.
In short, instead of v-model on computed set v-model for data property.
Full code:
<script src="//unpkg.com/vue/dist/vue.js"></script>
<script src="//unpkg.com/element-ui/lib/index.js"></script>
<div id="app">
<template>
<el-select v-model="ids" multiple placeholder="Select" #change="logit()">
<el-option v-for="item in availableRoles" :label="item.name" :value="item.id">
</el-option>
</el-select>
</template>
</div>
var Main = {
data() {
return {
availableRoles: [{
id: 1,
name: 'Admin'
}, {
id: 2,
name: 'Power User'
}, {
id: 3,
name: 'User'
}],
userRoles: [{'id':1, 'name':'Admin'}, {'id':3, 'name':'User'}],
ids: []
}
},
mounted() {
this.ids = this.userRoles.map(role => role.id);
},
methods: {
logit: function() {
console.log(this.ids);
}
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')

Categories

Resources