I have built a Vue app which fetches data from an endpoint and presents that data in a table with sortable columns.
The app is based on this React challenge which is to create a table of users and their properties, from the data provided in the endpoint.
Here are the user stories fulfilled:
- I can see a table of the Free Code Camp campers who've earned the most brownie points in the past 30 days.
- I can see how many brownie points they've earned in the past 30 days, and how many they've earned total.
- I can toggle between sorting the list by how many brownie points they've earned in the past 30 days and by how many brownie points they've earned total.
Here is my code (working example):
const endpoint = 'https://fcctop100.herokuapp.com/api/fccusers/top/recent'
const store = {
state: {
sortingBy: ''
}
}
new Vue({
el: '#app',
data() {
return {
data: [],
state: store.state
}
},
mounted() {
Vue.http.get(endpoint).then(response => {
this.data = response.body
}, response => {
console.warn('There was a data error:', response)
})
},
methods: {
sortByRecent() {
this.data = _.sortBy(this.data, 'recent').reverse()
store.state.sortingBy = 'recentDescending'
},
sortByAllTime() {
this.data = _.sortBy(this.data, 'alltime').reverse()
store.state.sortingBy = 'allTimeDescending'
},
getActiveClass(string) {
return {active: store.state.sortingBy.includes(string)}
}
}
})
#app {
display: flex;
flex-direction: column;
align-items: center;
}
.active {
font-weight: bold;
}
button {
font-size: 20px;
}
img {
border-radius: 50%;
height: 30px;
width: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.4/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-resource/1.0.3/vue-resource.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>
<div id="app">
<button @click="sortByRecent">Sort by Recent Points</button>
<button @click="sortByAllTime">Sort by All Time Points</button>
<table>
<thead>
<tr>
<td>#</td>
<td></td>
<td>Username</td>
<td :class="getActiveClass('recent')">Recent Points</td>
<td :class="getActiveClass('allTime')">Total Points</td>
</tr>
</thead>
<tr v-for="(user, index) in data">
<td>{{index + 1}}</td>
<td>
<img :src="user.img">
</td>
<td>{{user.username}}</td>
<td>{{user.recent}}</td>
<td>{{user.alltime}}</td>
</tr>
</table>
</div>
Here is a repo with all the code (bootstrapped with vue-loader
webpack).
My questions are:
- I have placed a method for computing a CSS classname in
methods
-getActiveClass
. In the documentation, it specifies that such methods can live inside thecomputed
object:
We can also bind to a computed property that returns an object.
However when doing so, I get the following console error in the browser:
Uncaught TypeError: _vm.getActiveClass is not a function
Why does placing this method inside a computed
object render this error?
My project was bootstrapped with
vue-loader
'swebpack
preset. In order to make the API call to my endpoint, I had toimport
Vue
so that I coulduse
vue-resource
. Should the API call be made inmain.js
and then passed in as a prop toApp.vue
to avoid importingVue
in multiple places?The data is received from the API call in any of the lifecycle methods
beforeCreate
,created
,beforeMount
andmounted
. Which is the correct one for it to go?Does it make sense for this code to all live in one single file component, or should it be split up into separate smaller components?