Social application with Vue.js and GO
Create and serve a twitter like application with vue.js and golang PART 3: COMPONENTS & SLOTS
This is the third part of this serie. Check here all the parts:
- Part1: Setup
- Part2: Getting started with VUE
- Part3: Components & slots (this)
- Part4: Vuex first setup
- Part5: VUEX finalization
- Part6: Forms and data in Vuex
- Part7: Connection with golang server
- Part8: Token-based authentication
- Part9: Store authentication token with indexedDB
In this lesson we are going to add some frontend functionalities, and by doing this we’ll learn a little more about using components and how to extend them with slots.
Main target here is to update the frontend project, you can find the code here.
Reusing components for posts
In the last lesson we created a list where we could see the posts of a user. Now, that view was not really nice, so here we are going to add css to make it a little better.
Additionally, we are going to create a card component that we’ll use again in other places in our application, so that the feeling that a user will have overall will be always the same.
Create a new component in the UI folder, and call it “BaseCard.vue”. Inside write the following code:
The style tag is actually filled with the minimum code that lets the application have a better look, but of course this is for demonstrative purpouses.
In this example, we have set a type, Boolean, and a default value of false for the “expandable” prop.
The data property contains only a value that indicates if the card actually is or is not expanded, and we have a method “toggleDetails” that toggles the expansion of the card.
There is also another configuration option that we have never seen before: “computed”.
This is an object containing functions that can be actually used as data values. So we can use them (also in the template) as if they were data values (no parentheses needed), and they also have reactive behaviour.
In fact, vue internally knows if some dependency of a computed value is changed, and re-evaluate the computed method only when needed. In our code, the messageValue computed properties will automatically be re-evaluated only when “this.expanded” changes.
Note that in the methods and computed properties we can use any other data, method or computed property using the keyword “this”, as if we were in an object of a class.
Lastly, the template: here there are two new things added, v-if and the slots.
The v-if construct creates or deletes an element from the DOM depending on the validity of a condition. This have to be written exactly as with the v-for, so we can also insert a little logic here (but normally is always better create a computed property or a method to do this, so we can have more separation from code).
In our example, the header section is rendered only if there is a $slots.header variable set.
Last and more important point, is the use of slots. Actually, using a slot in a component let the developer to insert from the outside some content and then extends the internal component.
It works like this: everything that is inserted in the father template into the value of the component tag of the child, is actually inserted where the “slot” tag is in the child component. This is all you need to do in case of only one slot.
If you need to set more then one slot, like in the example above, you can insert “named slots” in the children, so slots have a name parameter.
In this last scenario, one slot can also be left without name, and this will be actually called “default slot”. In the father, in this case, the value to be replaced should be placed inside an additional tag “template” and a parameter “v-slot:slotName” where slotName is the name of the slot of the child.
Again in the example we need to insert in the father a “<template v-slot:header>” tag for inserting into the header slot.
Now in the file SinglePost.vue we can change the template to use this component BaseCard in the actual SinglePost template:
Here we used a card that can be expanded if there are some comments, so actually the post object is going to have an upgrade to also contain them.
In the header we can see the title of the post, and as a footer we inserted another list of cards that contains each a comment.
For semplicity of code we used the same structure for comment and post objects, so they can share some functions (like “postTitle”).
Next thing to do, go in the Posts.Vue component and change the “posts” variable to contain some comments in every post, i.e.
We did not import the BaseCard into our component: because we’ll propably reuse this “Base” component a lot inside of our app, we can import it inside the initial Vue object, in main.js, and then set it in the “components” configuration parameter of the Vue global instance.
Changing the about page
Just to complete a little more the app, also change the “About.vue” component in a User.vue, that will show the user actually logged in and his posts.
This is actually self explainatory: the page is a simple one with a title consisting of the user’s username and shows a little description before displaying all of his posts. Actually the data is still some dummy block of objects, we’ll fix that later.
Setting a “title” parameter in the post-list, requires to also set that value in the props configuration parameters of the child component. Moreover, having removed the “About” component, we have to also update the index.js file inside the router to point to this new component.
At this point, it is mandatory a little explanation regarding the vue router: it is actually a component that lets you organize, maintain and correct the routing between different pages in your application. In a PWA the page is not loaded from the server each time, but this behaviour is actually simulated by the code, and this is what the router actually does.
First thing to do, is to check if in the main.js file the router is actually imported and registered in the vue application.
The router lets the application to have different pages, and show them only when called. Also it interacts with the browser “back” and “forward” buttons, so that this will seem to the user as if multiple pages are called and showed, while in reality only the routed piece of the page is changed by scripts.
Looking at the index.js file in the router folder we can see also the configuration of the router:
This first line instruct Vue to use the VueRouter. Write at the end of the router file:
Essentially it creates a VueRouter and export it, using as base url the base url of the application, using mode “history”, so it will use the history pushstate API to achieve url navigation (more HERE ) and then pass at the constructor the list of the routes that it will have to use.
This list of routes is defined in the lines before this construct:
This is a list of objects that defines the actual routes that can be called from the router. In each object is set the path of the url (so, in the example, the root will be served by the first route, while the “/user” path by the second), a name, and the component that will be used to render the router view on that route.
The name is normally used in the router links to reference the route of the link decoupling it from the url (we have done it before, in the application bar, the router-links tag have a to parameter that points to an object with a name parameter set, remember?)
At last, we have the props configuration parameter, set to true in the last route: with that we instruct the vue-router that the router-links can pass some props to the component. This is important, because the default behaviour of the router is to not pass these props.
Having set this to true, in future we will be able to change the calls to the User page to have a different user.
With this we have done a little regression on vue router, if you now launch the frontend the application starts looking better, the data is still static and cannot be changed by the user, but we’ll be there in the next couple of lessons.