Reputation: 51
Here is an example of my table.
+----+--------+---------------+
| ID | User | Creation_date |
+----+--------+---------------+
| 1 | Bob | 2020-05-05 |
| 2 | Bob | 2020-05-06 |
| 3 | Bob | 2020-06-06 |
| 4 | John | 2020-05-04 |
| 5 | John | 2020-05-07 |
| 6 | John | 2020-06-10 |
| 7 | Robert | 2020-04-04 |
| 8 | Robert | 2020-05-05 |
| 9 | Robert | 2020-06-07 |
| 10 | Robert | 2020-09-09 |
+----+--------+---------------+
What I want: I want to show only the first value of each "User" and when clicked on the row to toggle the hidden values.
+----+--------+---------------+
| ID | User | Creation_date |
+----+--------+---------------+
| 1 | Bob | 2020-05-05 |
| 4 | John | 2020-05-04 |
| 7 | Robert | 2020-04-04 |
+----+--------+---------------+
My current code, I have tried multiple different approach but I can't figure out how to show only the first value and hide the rest.
<template>
<div>
<table>
<thead>
<tr>
<th>ID</th>
<th>User</th>
<th>Creation date</th>
</tr>
</thead>
<tbody>
<template v-for="row in local_users">
<tr @click="row.isVisible = !row.isVisible">
<div v-if="row.isVisible">
<td>{{row.user_id}}</td>
<td>{{row.username}}</td>
<td>{{row.creation_date}}</td>
</div>
</tr>
</template>
</tbody>
</table>
</div>
</template>
<script>
export default {
props: ["users"],
data() {
return {
local_users: [],
};
},
created() {
this.local_users = this.users.map((e) => {
return { ...e, isVisible: true };
});
},
};
</script>
Upvotes: 0
Views: 654
Reputation: 10729
I moved the codes (clone this.users
to this.local_users
) from created()
to watch of this.users
, otherwise the local_users
will not be synced when props=users
is updated.
Then uses two data properties to store the visible state (invisibles
) and the index for first username (firstMatches
). firstMatches
will be reset when this.users
is changed.
Below is the demo:
Vue.component('v-table',{
template:`
<div>
<table>
<thead>
<tr>
<th>ID</th>
<th>User</th>
<th>Creation date</th>
</tr>
</thead>
<tbody>
<template v-for="(row, index) in local_users">
<tr @click="toggle(row)" :key="index" v-if="firstMatches[row.username] === index || !invisibles[row.username]">
<td>{{row.user_id}}</td>
<td>{{row.username}}</td>
<td>{{row.creation_date}}</td>
</tr>
</template>
</tbody>
</table>
<pre>{{invisibles}}</pre>
</div>
`,
props: ["users"],
data() {
return {
local_users: [],
firstMatches: {},
invisibles: {}
};
},
watch: {
users: {
handler: function (newVal) {
this.firstMatches = {}
this.local_users = (newVal || []).slice()
this.local_users.forEach((e, i) => {
if (!(e.username in this.firstMatches)) {
this.firstMatches[e.username] = i
}
})
},
immediate: true
}
},
methods: {
toggle: function (row) {
this.$set(this.invisibles, row.username, !this.invisibles[row.username])
}
}
})
new Vue ({
el:'#app',
data () {
return {
users: [
{user_id: 1, username: 'Bob', creation_date: '2020-01-01'},
{user_id: 2, username: 'Bob', creation_date: '2020-01-02'},
{user_id: 3, username: 'Tom', creation_date: '2020-01-03'},
{user_id: 4, username: 'Bob', creation_date: '2020-01-04'},
{user_id: 5, username: 'Tom', creation_date: '2020-01-05'},
{user_id: 6, username: 'Sun', creation_date: '2020-01-05'},
]
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<div class="container">
<div>
<v-table :users="users"></v-table>
</div>
</div>
</div>
Upvotes: 1