laravue.dev: Taking tags-view to the next level

In 2019 I’ve mentioned that I’m building a new Reporting/BI application. And I decided to use the laravue.dev administration panel, which is (quote) “A magical administrative interface for Laravel built by VueJS and Element UI“.

The main reason why I decided to use laravue.dev is because it’s the only sample I’ve found using Laravel+VueJS as a complete template, with a ready-to-use CRUD API, user/permission/role management etc. My first choice was to use vuexy which is awesome, but unfortunately their “Laravel+VueJS” implementation is using Laravel only as a site loader, no connection at all between frontend and backend, not even as a sample, meaning that we had to implement everything from scratch.

Anyway, getting back to our current selection, laravue.dev.

As soon as you understand the logic and the structure, it’s pretty easy to either start modifying existing modules or start building your own.

One of the features I’ve found interesting and quite functional is the nice use of tags, to switch between opened “pages” (or tabs, menu options etc, call them in any way you like). But I’ve noticed that whenever you switch from “page” to “page”, instead of keeping the pages somewhere in the background (which makes sense, this would take the memory usage up to the skies) it creates them from scratch.

This could make sense but there’s a catch. Let’s take the user’s example. In the Profile.vue page, we see the following:

 

created() {
    const id = this.$route.params && this.$route.params.id;
    this.getUser(id);
},
methods: {
    async getUser(id) {
        const { data } = await userResource.get(id);
        this.user = data;
    },
}

 

So, based on the code, on the creation time, the component makes the call to the userResource.get() function to retrieve the user’s profile data through a backend API call. But, when switching to another tab and getting back to this one, the call is done again. Which has two cons: server overload and delay to display the data (since it makes the API call every single time). On the existing example it’s not noticeable because the data are quite few and the database structure pretty simple, but what about a more complicated database scheme?

Having these in mind, I came up with the following solution, which works really smooth and nice:

 

created() {
    const id = this.$route.params && this.$route.params.id;
    this.getUser(id);
},
methods: {
    async getUser(id) {
        // Do we have the current path in storage?
        var data = sessionStorage.getItem(this.$router.currentRoute.fullPath);
        if (data) {
            // If yes, apply the data on the component
            this.user = JSON.parse(data);
        } else {
            // Otherwise, retrieve them as usual
            const { data } = await userResource.get(id);
            this.user = data;

            // And store them in the sessionStorage, to be able to retrieve them later on.
            sessionStorage.setItem(this.$router.currentRoute.fullPath, JSON.stringify(data));
        }
    },
}

 

In this approach, as you can see, I’m using the sessionStorage in order to temporary store the component’s data (based on the currentRoute.fullPath variable). If the data exist in the sessionStorage, I retrieve them and populate the page immediately otherwise I’m making the normal userResource.get(id) call and update the sessionStorage accordingly.

So, in the default data sample provided by the project itself, if we browse to the user with id=2, the url will be something like this:

http://127.0.0.1:8000/#/administrator/users/edit/2

This will result to a new entry in the sessionStorage, with the following information:

 

key = /administrator/users/edit/2
value = {
    id: 2,
    name: "Manager",
    email: "[email protected]",
    roles: ["manager"],
    …
}

 

This way, both switch-tag-speed and server-overloading issues are solved.

Share your thoughts