Because this is my very first attempt to create a data grid with Vue, I would like to know about all misconceptions used in my approach. Whomever points to the most important shortcoming / weakness in my approach will receive 50 points :).
var url ='https://api.mockaroo.com/api/b5f38710?count=20&key=cdbbbcd0'
new Vue({
el: '#datagrid',
data: {
columns: {
id: 'ID',
nick: 'Nick name',
first: 'First name',
last: 'Last name'
},
users: [],
query: '',
prevKey: 'id',
orderDesc: false
},
methods: {
async loadUsers () {
var result = await axios.get(url)
this.users = result.data
this.query = ''
this.prevKey = 'id'
this.orderDesc = false
},
clearQuery () {
this.query = ''
},
sortUsers (e) {
var key = e.target.dataset.key
if (this.prevKey === key) {
this.users.reverse()
this.orderDesc = !this.orderDesc
} else {
this.users = _.sortBy(this.users, key)
this.orderDesc = false
this.prevKey = key
}
},
filterUsers (users) {
return _.filter(users, user =>
_.find(user, prop =>
new RegExp(this.query, 'i').test(prop)
)
)
},
updateQuery: _.debounce(function (e) {
this.query = e.target.value
}, 350)
}
})
#datagrid {
width: 98%;
margin: 10px auto;
padding: 2px;
background-color: white;
border: 2px solid #3F51B5;
overflow: hidden;
}
.table {
display: table;
width: 100%;
font-size: 14px;
font-family: Arial, sans-serif;
color: #263238;
}
.thead {
display: table-header-group;
}
.tbody {
display: table-row-group;
}
.tr {
display: table-row;
}
.td {
display: table-cell;
position: relative;
}
.thead .td {
padding: 5px 14px;
background-color: #3F51B5;
color: white;
font-weight: bold;
text-align: center;
cursor: pointer;
}
.tbody .td {
padding: 4px;
color: #263238;
text-align: center;
}
.tr .td:not(:last-child) {
border-right: 2px solid white;
}
.tbody .tr:hover .td {
background-color: #C5CAE9;
}
.tbody .tr:hover .td:not(:last-child) {
border-right: 2px solid #C5CAE9;
}
.tools {
margin: 10px;
box-sizing: border-box;
}
.tools:after {
content: "";
display: block;
clear: both;
}
.source {
display: block;
float: left;
}
.search {
float: right;
}
.arrow {
display: inline-block;
position: absolute;
width: 0;
height: 0;
margin-left: 5px;
margin-top: 5px;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
transition: all .6s;
}
.asc {
border-bottom: 6px solid white;
}
.desc {
border-top: 6px solid white;
}
.users-move {
transition: transform .6s;
}
.users-enter-active, .users-leave-active {
transition: all .6s;
}
.users-enter, .users-leave-to {
opacity: 0;
transform: translateY(30px);
}
<script src="https://unpkg.com/[email protected]/underscore-min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/axios.min.js"></script>
<div id="datagrid">
<div class="tools">
<button class="source" @click="loadUsers">
Load some fake data from mockaroo.com
</button>
<div class="search">
<input type="text" @input="updateQuery" :value="query">
<button class="clear" @click="clearQuery">clear</button>
</div>
</div>
<div class="table">
<div class="thead" @click="sortUsers">
<div class="tr">
<span v-for="(col, key) in columns" class="td" :data-key=key>
{{ col }}
<span
v-if="prevKey === key"
:class="['arrow', orderDesc ? 'desc' : 'asc']">
</span>
</span>
</div>
</div>
<transition-group name="users" tag="div" class="tbody">
<div class="tr" v-for="row in filterUsers(users)" :key="row.id">
<span class="td" v-for="column in row">{{ column }}</span>
</div>
</transition-group>
</div>
</div>
If the snippet doesn't load the data: Mockaroo has an SSL certificate problem. So you must open the data URL in your browser first, confirm the security exception, delete the downloaded JSON and then run this code snippet again.