In a previous tutorial, I showed how you can create a ‘Show More’ button that utilizes AJAX in order to call and present more data without reloading the page. I thought I’d also show you how you can accomplish a similar task with VueJS.
Did you know that Alpas comes with VueJS pre-loaded out-of-the-box? It’s just another way in which Alpas reduces setup time and friction so that you can quickly start coding awesome web apps. 💪🏽
If you are unfamiliar with VueJS, it is a JavaScript framework that drastically improves your ability to create interactive and powerful front-ends. If you are familiar with Angular and like it, then you will love VueJS. Here is a comparison of VueJS vs Angular (and other JS frameworks). If you want to learn VueJS,Laracasts has an informative training series to get you started.
The great thing about VueJS is that I can easily create a reusable front-end component. Also, a lot of the processing I previously used to generate a bunch of the html creation on the Alpas back-end, that I then pushed to the front-end to display, can now be separated out a bit better. I prefer not to be mucking around with generating HTML on the back-end as I want that to be done in the front-end as much as possible.
Let’s get the show on the road —
Step 1: Create VueController and update routes
I want to first create a new controller, that I will call VueController.
class VueController : Controller() {
fun vue(call: HttpCall) {
val images = Images
.latest()
.take(5)
.toList()
call.render("vue") {"images" to images }
}
fun vuemore(call: HttpCall){
if(call.isAjax) {
var last_id = call.jsonBody?.get("id")
val images = last_id?.let {
Images
.latest()
.drop( it as Int)
.take(5)
.toList()
}
if (images != null) {
call.reply(images.toJson())
}
}
}
Look at how much cleaner this is for the controller! All of the ugly html creation I was doing in the back-end is now not needed, yay! 🙌
In the routes.kt file, I will add the following routes for the Vue example.
get("/vue", VueController::vue)
post("/vue/vue-more", VueController::vuemore)
Alrighty, that’s all we really need to do in the Alpas backend. Now, let’s move to the front-end and work on a Vue component.
Step 2: Create the Show More Vue component
As I mentioned before, VueJS is already available in the Alpas starter template; so, no need to install VueJS and we can get rollin’ on creating a component right away.
Under the JS > Components folder, create a new file namedShowMore.vue. And now, the code:
<template>
<div>
<li v-for="image in images" class="p-4 bg-white rounded-lg mb-3 flex flex-st">
<div class="flex">
<div class="self-center">
<a :href="image.src" target="_blank">
<img class="h-20 w-20 object-cover rounded-lg" :src="image.src">
</a>
</div>
<div class="ml-6 pr-4 flex-1">
<div class="text-xl font-bold text-gray-900"> {{ image.name }} </div>
</div>
</div>
</li>
<div id="load\_more">
<button @click="showMore" type="button" name="show_more_button" class="font-semibold uppercase py-2 px-4 rounded-lg inline-flex" data-id="5" id="show_more_button">
<svg class="fill-current h-4 w-4 mr-2 mt-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"/></svg>
{{ buttonText }}
</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
images: [],
buttonText: 'Show More',
id: 5
}
},
methods: {
showMore() {
this.buttonText = 'Loading more images...';
axios.post('/vue/vue-more', {id:this.id}).then(response => {
let newData = [];
if(response.data.length !== 0 ){
for (let i = 0; i < response.data.length; i++){
newData.push(response.data[i]);
}
} else {
$('#show_more_button').remove();
}
this.images = this.images.concat(newData);
this.id += 5;
});
this.buttonText = 'Show More';
}
}
};
</script>
The template section is the HTML template that the component will use. Notice that the li tag has a ‘v-for’ label. This is an indicator to Vue to use a for-loop following the pattern specified in the quotes. In this case, we will cycle through the images as defined in the data source in the script section.
You can also see other variables identified by a colon ‘:’ if within a tag or by curly braces ‘{‘ if outside of a tag. These will be replaced by the logic and data sources defined in the script section.
A lot of the logic is launched when a user clicks the ‘Show More’ button. Under the Methods section, you can see the ShowMore() method that is initiated on click of the Show More button. Following the logic trail, you can see that we use the Axios library to make an Ajax call to the back-end. Axios works very well with VueJS. Also, since Axios sends CSRF tokens via the header, we don’t need to add that information in this example as Axios will automatically send the token and Alpas will recognize it.
We pass along an ‘id’ to the Alpas backend, which is basically a reference point to know where to start pulling new data from. The front-end will then receive the new data in Json format, which we will then check to see if data is present. If present, then we cycle through and add new image data to the list. If not, we hide the Show More button as there are no more results to display.
That’s the gist of the logic and the component. And again, the great thing is that this component can now be easily reused.
Step 3: Register the new component
Now that we have created the component, we now need to register it so that is can be referenced when we add it to our Pebble templates.
It’s very easy to register the component. Head over to the App.js file.
Vue.component('show-more', require('./components/ShowMore').default)
Boom! Component registered. Now, to use the component, all I will need to do is add to my HTML.
Step 4: Add component to your HTML (Pebble file)
Let’s add a new Pebble file called vue.peb under the templates folder and add in the following code:
<div id="app">
<h1 class="text-lg">This example uses Vue.js. <a href="/" class="text-lg text-blue-600 hover:text-blue-400">Check out the JQuery example</a></h1>
<ul class="" id="image_list">
{% for image in images %}
<li class="p-4 bg-white rounded-lg mb-3 flex flex-st">
<div class="flex">
<div class="self-center">
<a href="{{ image.src }}" target="_blank">
<img class="h-20 w-20 object-cover rounded-lg" src="{{ image.src }}">
</a>
</div>
<div class="ml-6 pr-4 flex-1">
<div class="text-xl font-bold text-gray-900"> {{ image.name }} </div>
</div>
</div>
</li>
{% endfor %}
{% csrf %}
<show-more></show-more>
</ul>
</div>
Done.
With my implementation, I call data from the backend on initial page load and then use the standard Pebble template tags to cycle through and display the data. Then, you can see the tags. On page load, this will show only the button as the list items won’t have data to display yet. The user can then click on ‘Show More’ which will put the functionality into action — data will be requested to and and received from the back-end and VueJS will use the data and follow the HTML template to display new results.
Easy and powerful. 😎
Please note — when you are working with templates in this manner (mainly with modifying the app.js file), you will need to recompile. Install Yarn and run Yarn Watch. 👍
Top comments (0)