I'm new in vue.js, I would like to filter the following table by "Director ID".
When I load the page I would like to show only rows where director ID is 18. I need the table to filter right away without any user input. I would like to "hardcode" the ID 18 in to the function.
Thank you for your help!
<template>
<div>
<div class="row">
<div class="col"><h1 class="mt-3">List of all Movies</h1></div>
</div>
<table class="table">
<thead>
<tr>
<th>Movie ID</th>
<th>Title</th>
<th>Release Year</th>
<th>Director ID</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="movie in movies" :key="movie.id">
<td>{{ movie.id }}</td>
<td>{{ movie.title }}</td>
<td>{{ movie.releaseYear }}</td>
<td>{{ movie.director.id }}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data: function () {
return {
movies: [
{
id: 1,
title: "They All Lie",
releaseYear: 1989,
director: {
id: 18,
firstName: "Darci",
lastName: "Overill",
nationality: "China",
birthdate: "07/13/1973",
},
},
{
id: 2,
title: "Star Wars",
releaseYear: 1997,
director: {
id: 18,
firstName: "Darci",
lastName: "Overill",
nationality: "China",
birthdate: "07/13/1973",
},
},
{
id: 3,
title: "Mamma mia",
releaseYear: 2005,
director: {
id: 19,
firstName: "John",
lastName: "Smith",
nationality: "USA",
birthdate: "07/13/1980",
},
},
],
};
},
};
</script>
What if you change the tr to:
<tr v-for="movie in movies" :key="movie.id" v-if="movie.director.id === 18">
UPDATE
We wrote at the same time with #tuhin47.
I prefer his way to be honest with only a minor change in computed.
I changed the el to movie just to be more clear :)
computed: {
filteredMovies() {
return this.movies.filter((movie) => movie.director.id === 18);
},
},
You can use a computed property for filtering data and v-for the filtered data.
Here is the codesandbox
<tbody>
<tr v-for="movie in filteredMovies" :key="movie.id">
<td>{{ movie.id }}</td>
<td>{{ movie.title }}</td>
<td>{{ movie.releaseYear }}</td>
<td>{{ movie.director.id }}</td>
</tr>
</tbody>
Here is the computed property:
computed: {
filteredMovies() {
return this.movies.filter((el) => el.director.id === 18);
},
},
Related
Trying to display Total records. Students.length works the first time on page load thanks to the created() method. However, calling filteredStudents(), is out of date. What is the easiest way to make this reactive?
<template>
<div class="d-inline-flex flex-row p-4 col-2">
Total record(s): {{ recordCount }}
</div>
<table class="table border table-striped table-hover">
<thead class="bg-secondary">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr v-for="student in filteredStudents()" :key="student._id">
<td>{{ student.firstName }}</td>
<td>{{ student.lastName }}</td>
<td>{{ student.email }}</td>
</tr>
</tbody>
</table>
</template>
<script>
import MixinCommon from '#/mixins/common.js'
export default {
data() {
return {
searchTerm: '',
Students: [],
studentcount: 0
}
},
created() {
this.Students = this.getSutdentList()
},
computed: {
recordCount() {
return this.Students.length
}
},
mixins: [MixinCommon],
methods: {
filteredStudents() {
return this.searchStudentList(this.searchTerm.toUpperCase(), this.Students)
},
}
}
</script>
I don't know the implementation of the searchStudentsList method, but you could try using the filteredStudents as a computed property, or making a watch property on the searchTerm in order to make the search again:
Using computed:
<template>
<div class="d-inline-flex flex-row p-4 col-2">
Total record(s): {{ recordCount }}
</div>
<table class="table border table-striped table-hover">
<thead class="bg-secondary">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr v-for="student in filteredStudents" :key="student._id">
<td>{{ student.firstName }}</td>
<td>{{ student.lastName }}</td>
<td>{{ student.email }}</td>
</tr>
</tbody>
</table>
</template>
<script>
import MixinCommon from '#/mixins/common.js'
export default {
data() {
return {
searchTerm: '',
Students: [],
studentcount: 0
}
},
created() {
this.Students = this.getSutdentList()
},
computed: {
recordCount() {
return this.Students.length
},
filteredStudents() {
return this.searchStudentList(this.searchTerm.toUpperCase(), this.Students)
},
},
mixins: [MixinCommon],
}
</script>
Using watch property:
<template>
<div class="d-inline-flex flex-row p-4 col-2">
Total record(s): {{ recordCount }}
</div>
<table class="table border table-striped table-hover">
<thead class="bg-secondary">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr v-for="student in filteredStudents" :key="student._id">
<td>{{ student.firstName }}</td>
<td>{{ student.lastName }}</td>
<td>{{ student.email }}</td>
</tr>
</tbody>
</table>
</template>
<script>
import MixinCommon from '#/mixins/common.js'
export default {
data() {
return {
searchTerm: '',
Students: [],
filteredStudents: [],
studentcount: 0
}
},
created() {
this.Students = this.getSutdentList()
this.filteredStudents = this.searchStudentList(this.searchTerm.toUpperCase(), this.Students)
},
computed: {
recordCount() {
return this.Students.length
}
},
watch: {
searchTerm(newValue) {
this.filteredStudents = this.searchStudentList(newValue.toUpperCase(), this.Students)
}
}
mixins: [MixinCommon],
}
</script>
I'm making a table listing with vuejs. My data from the database is as above. I'm transferring the data that comes with axios to "data.userList". What I want to do is; if "transaction_type" I want to edit. If I try to convert the data from the table, it will be too long. what should i do for him?
Examle:
I want to make the conditions I have written more regular. Considering that there are thousands of "transaction_types" like this, it's a lot of work. how can i edit this?
"transaction_type" I want to rename it according to the type of incoming data.
const app = new Vue({
el: '#app',
data: {
userList: [{
id: 1,
name: "Prem",
age: 18,
status: "close",
gender: "male",
transaction_type: 'initial_account_balance'
},
{
id: 2,
name: "Chandu",
status: "close",
age: 20,
gender: "female",
transaction_type: 'contact_debit'
},
{
id: 3,
name: "Jong",
status: "open",
age: 21,
gender: "female",
transaction_type: 'contact_credit'
},
{
id: 4,
name: "Steew",
status: "open",
age: 33,
gender: "male",
transaction_type: 'account_debit'
},
{
id: 5,
name: "Abdollah",
status: "open",
age: 26,
gender: "female",
transaction_type: 'account_credit'
},
{
id: 6,
name: "Jerry",
status: "open",
age: 35,
gender: "male",
transaction_type: 'account_debit'
}
]
}
});
<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.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<script src="https://unpkg.com/vue-router#2.0.0/dist/vue-router.js"></script>
<div id="app">
<table class="table table-hover table-striped table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Status</th>
<th>Type</th>
<th>Gender</th>
</tr>
</thead>
<tbody>
<tr v-for="(user, i) in userList" class="position-relative">
<td>{{ user.name }}</td>
<td>{{ user.age }}</td>
<td>{{ user.status }}</td>
<td>
<p v-if="user.transaction_type ==='initial_account_balance'">Opening Balance</p>
<p v-if="user.transaction_type ==='contact_debit'">Customer Advance</p>
<p v-if="user.transaction_type ==='contact_credit'">Customer</p>
<p v-if="user.transaction_type ==='account_debit'">Customer sales</p>
<p v-if="user.transaction_type ==='account_credit'">Customer Buy</p>
</td>
<td>
{{ user.gender }}
<!-- This can be placed in any of the <td>'s -->
<a class="stretched-link" :href="`#${user.id}`"></a>
</td>
</tr>
</tbody>
</table>
</div>
One idea is to give the user a select based on transaction types found in the data. filter the large data set with the user's selection...
const app = new Vue({
el: '#app',
data: {
xactionType: '',
userList: [{
id: 1,
name: "Prem",
age: 18,
status: "close",
gender: "male",
transaction_type: 'initial_account_balance'
},
{
id: 2,
name: "Chandu",
status: "close",
age: 20,
gender: "female",
transaction_type: 'contact_debit'
},
{
id: 3,
name: "Jong",
status: "open",
age: 21,
gender: "female",
transaction_type: 'contact_credit'
},
{
id: 4,
name: "Steew",
status: "open",
age: 33,
gender: "male",
transaction_type: 'account_debit'
},
{
id: 5,
name: "Abdollah",
status: "open",
age: 26,
gender: "female",
transaction_type: 'account_credit'
},
{
id: 6,
name: "Jerry",
status: "open",
age: 35,
gender: "male",
transaction_type: 'account_debit'
}
]
},
computed: {
xactionTypes() {
return this.userList.map(e => e.transaction_type);
},
filteredData() {
return this.xactionType ? this.userList.filter(e => e.transaction_type === this.xactionType) : this.userList;
}
},
});
<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.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<script src="https://unpkg.com/vue-router#2.0.0/dist/vue-router.js"></script>
<div id="app">
<div>
<label for="xactionType">Select transaction type:</label>
<select id="xactionType" v-model="xactionType">
<option v-for="(type, i) in xactionTypes" :key="i" :value="type">{{type}}</option>
</select>
</div>
<table class="table table-hover table-striped table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Status</th>
<th>Type</th>
<th>Gender</th>
</tr>
</thead>
<tbody>
<tr v-for="(user, i) in filteredData" class="position-relative">
<td>{{ user.name }}</td>
<td>{{ user.age }}</td>
<td>{{ user.status }}</td>
<td>
<p v-if="user.transaction_type ==='initial_account_balance'">Opening Balance</p>
<p v-if="user.transaction_type ==='contact_debit'">Customer Advance</p>
<p v-if="user.transaction_type ==='contact_credit'">Customer</p>
<p v-if="user.transaction_type ==='account_debit'">Customer sales</p>
<p v-if="user.transaction_type ==='account_credit'">Customer Buy</p>
</td>
<td>
{{ user.gender }}
<!-- This can be placed in any of the <td>'s -->
<a class="stretched-link" :href="`#${user.id}`"></a>
</td>
</tr>
</tbody>
</table>
</div>
I have a v-for loop that is going to spit out multiple rows of inputs that I would like to save each separate row to an array object dynamically.
v-for:
<table class="table m-0">
<tbody>
<tr v-for="fund in defaultFunds">
<td>
{{fund.name}}
<b-input v-model="newEntries[fund.id]['id']"
:value="fund.id"
name="entryFund"
type="text"
class="d-none"
:key="fund.id" />
</td>
<td>
<b-input v-model="newEntries[fund.id]['amount']"
name="newFundAmount"
id="newFundAmount"
type="text"
placeholder="Amount"
:key="fund.id"/>
</td>
</tr>
</tbody>
</table>
Desired array (using example of entering 2 rows):
newEntries: [
{ id: '1', amount: '50.00' },
{ id: '2', amount: '123.45' }
],
I load newEntries as an empty array by default. I don't know how to get the kind of array object I want with v-for. With the above code I end up with this:
newEntries: [null, '50.00', '123.45']
What am I doing wrong?
Do you want something like this:
https://jsfiddle.net/e6L5seec/
<div id="app">
newEntries: {{ newEntries }}
<table>
<tr v-for="(fund, index) in defaultFunds">
<td>{{ fund.name }}</td>
<td>
<input v-model="newEntries[index].id"
name="entryFund"
:value="fund.id"
type="text" />
</td>
<td>
<input v-model="newEntries[index].amount"
name="entryFund"
type="text" />
</td>
</tr>
</table>
</div>
new Vue({
el: "#app",
data: function() {
return {
defaultFunds: [
{
id: 0,
name: 'fund 0'
},
{
id: 1,
name: 'fund 1'
}
],
newEntries: [{}, {}]
}
},
methods: {
}
});
I'm really new to vuejs and I was wondering if it is possible to trigger the checkbox by clicking the table row.
here's a fiddle for you to play.
https://jsfiddle.net/50wL7mdz/265410/
HTML
<div id="app">
<table>
<tbody>
<tr v-for="cat in categories" #click="selectCat(cat)">
<td><input type="checkbox" :value="cat" v-model="selected" name="" id=""></td>
<td>{{ cat.code}}</td>
<td>{{ cat.name }}</td>
</tr>
</tbody>
</table>
<button #click="checkData()">Check</button>
</div>
VUEJS
new Vue({
el: '#app',
data() {
return {
categories: [
{code:'HW', name:'Hardware'},
{code:'SW', name:'Software'},
{code:'OS', name:'Office Supplies'}
],
selected:[]
}
},
methods:{
selectCat(cat){
this.selected.push(cat);
},
checkData(){
alert(1);
console.log(this.selected);
}
}
})
Thanks in advance.
Add a selected model to your categories and switch that attribute on row click like so:
<div id="app">
<table>
<tbody>
<tr v-for="(cat, index) in categories" :key="index" #click="cat.selected = !cat.selected">
<td><input type="checkbox" v-model="cat.selected"></td>
<td>{{ cat.code}}</td>
<td>{{ cat.name }}</td>
</tr>
</tbody>
</table>
</div>
new Vue({
el: '#app',
data() {
return {
categories: [
{code:'HW', name:'Hardware', selected: false},
{code:'SW', name:'Software', selected: false},
{code:'OS', name:'Office Supplies', selected: false}
]
}
},
methods:{
}
})
Manipulating the state of natives components should always be done by changing their v-model, rather than going into the DOM and and setting a selected attribute. Basically let your model define the state of your view.
Here's another version that'll use a separate array for handling the selected state:
<div id="app">
<table>
<tbody>
<tr v-for="(cat, index) in categories" :key="index" #click="toggleSelect(cat)">
<td><input type="checkbox" :checked="selected.includes(cat.code)"></td>
<td>{{ cat.code}}</td>
<td>{{ cat.name }}</td>
</tr>
</tbody>
</table>
</div>
new Vue({
el: '#app',
data() {
return {
categories: [
{code:'HW', name:'Hardware'},
{code:'SW', name:'Software'},
{code:'OS', name:'Office Supplies'}
],
selected: ['HW']
}
},
methods:{
toggleSelect (cat) {
if (this.selected.includes(cat.code)) {
this.selected.splice(this.selected.findIndex(v => v === cat.code), 1)
} else {
this.selected.push(cat.code)
}
}
}
})
I have a performance problem with VueJS. I have a table with X rows, which I load through an array. The problem is that when I change a single element of the array, it renders all the array again, and therefore, performs all the conditions again (v-if, if inside v-bind:class, etc.). I leave a jsfiddle where from a table, hide only 1 element, and update the whole table again.
https://jsfiddle.net/toledorobia/0twghfya/
$(function(){
var users = [];
for (var i = 1; i <= 100; i++) {
users.push({
id: i,
name: faker.name.findName(),
email: faker.internet.email(),
visible: true
});
}
var app = new Vue({
el: "#app",
data: {
users: users
},
methods: {
random: function() {
return faker.random.number();
},
toggleRows: function(){
this.users[5].visible = !$(this.$refs.togglerows).is(":checked");
}
}
});
});
<div id="app">
<div>
<input type="checkbox" ref="togglerows" v-on:click="toggleRows" /> Hide some rows
</div>
<table border="1" cellspacing="0">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr v-for="u in users" v-if="u.visible">
<td>{{ u.id + ' ' + random() }}</td>
<td>{{ u.name }}</td>
<td>{{ u.email }}</td>
</tr>
</tbody>
</table>
</div>
How can I avoid this behavior?
Thanks in advance.
Because everything is rendered in the same scope, when you show/hide the single row you want, Vue is forced to re-render all the rows. Instead, isolate the scope of the changes using a component.
Vue.component("row",{
props:["user"],
template:`
<tr>
<td>{{ user.id }}</td>
<td>{{random()}}</td>
<td>{{ user.name }}</td>
<td>{{ user.email }}</td>
</tr>`,
methods:{
random: function() {
return faker.random.number();
},
}
})
And your main template ends up looking like this:
<tbody>
<tr is="row" v-for="u in users" :key="u.id" v-if="u.visible" :user="u"></tr>
</tbody>
Here is the updated fiddle.