In the Part II of the Vuetiful Tabs series (you can read Part I here), we will use what we have learned so far and make a practical example with some real-world data. We will also customise the way the tabs are displayed to enrich the available information.
For inspiration we will use the stock tickers commonly found on finance web sites. An example of such display can be seen in the following picture:
Bitcoin is everywhere in the news currently, and everyone is talking about the price jumping up and down, so let’s use this as the theme for our task. We will also show how to download and use the pricing data from a publicly available API, and how to dynamically add tabs from search results.
Let’s make a plan first
When preparing a new feature, usually I like to have the steps needed beforehand in my mind or written on paper. After a bit of thinking, we come up with a list of things we need to do:
- Download the Bitcoin and other coins pricing data in order to take a look at what is available and usable for display.
- Make a design of tabs which will include the title of a coin, and some pricing indicators. Here we will only put some dummy data in order to check viability of design.
- Integrate the real data into the component. We will implement fetching the data from API at this point!
- Set tabs to display a couple of most popular coins by default.
- Implement the search feature into the toolbar for looking up other coins. If a coin is selected, we will dynamically add the tab into the collection.
- Test if everything works!
Downloading the pricing data
There are several providers of pricing data available online, some commercial and some free. After some searching I have decided to use CoinMarketCap as a data source for our example.
Disclaimer: Please note that neither me, nor my company Certissa-Analytics d.o.o. Croatia, are endorsing or are associated with any 3rd party company mentioned in this article, and are not involved with trading Bitcoins and/or other coins. We take no liability for data shown in this article. All use of 3rd party services is purely for informational purposes.
We can see that the structure contains an array of pricing information for every coin separately. After a bit examiming the data, we can decide on which information about the coins could be interesting to display:
- name: used for easier searching;
- symbol: we will use them for nice short tab titles;
- price_usd: price to be shown in US dollars
- 24h_volume_usd: the trade volume in the past 24 hours
- percent_change_24h: how much did the price increase or decrease in the past 24 hours
- percent_change_7d: how much did the price increase or decrease in the past week
Designing the tabs
After we examined what we have in the data, it’s time to start thinking about layout of the information. To keep up with the stock-like appearance of tabs, we first need to select what information goes where:
- Row 1: code
- Row 2: name
- Row 3: current price
- Row 4: change of price to previous day and week. On bigger screens, it makes sense to put this information next to each other. However, on smaller screens, the text might start overlapping so we will put it as two rows then. To achieve this easily, we can use Vuetify’s built-in Grid system.
- Row 5: trade volume
Designing the html template
For starters, we will fork the Codepen from Vuetify documentation. Based on what we learned previously, we come up with the following code for the html part:
As we can see, almost everything is the same like in documentation. Besides changing color, and adding the height and extension-height, the main difference is that we are putting more information in the tab title using the grid layout:
- Each row (except the fourth one) is represented with a flex element which spans all 12 columns (sized with xs12)
- For row 4 we use two flex elements — on larger screens we will use 6 columns for each data point (sized with sm6). On smaller screens they need to go into new rows so we use xs12 as the size. We also added icons to make the numbers less boring :)
Also important to note: we removed the tabs attribute from the <v-toolbar> component in order to prevent overriding the extension-height we manually set.
We can see in the next picture how our current design looks like:
As we are changing the number of visible tabs we will notice that after some number of them they start to get off-screen. To make them visible, we also added property to tabs to show pagination — this property is called show-arrows.
Making tabs look like this is not in line with Material Design guidelines, but every rule has an exception :)
Styling and formatting the text
We can see that the Material style for tabs is to make all captions uppercase. Let’s workaround it and override this and the font sizes. How do we know which classes to override? We use the developer tools from our browser to have a look at what kind of HTML markup does the Vuetify generate for Tabs component:
So we can see that each of the tabs is represented as a <div> element with the class tabs__div.
We will now edit the CSS part of the Codepen and apply the following styles:
The previous example was shown to demonstrate ability to override built-in styles as this might be the first thing to come to your mind. However, it is strongly advised not to use such approach:
- If you use tabs component in different places, overriding the style will have impact in all of the places!
- Unrelated issues might appear within the framework itself if a particular class/style is used also in another component.
Styling and formatting the text — THE PROPER WAY
Instead of touching the framework styles themselves, a better approach is to add a style which targets the elements which were added by us within the tabs:
- we add class=”customTabTitle” to the <v-tab> components
- we target the style of all <div>s within such tabs to get the same effect:
Binding to component data
We added a new property called coinData to the data collection, and updated the HTML as well to show the bound values with applied filter for a nicer number format. The updated template can be seen below:
Don’t forget to also bind the tab contents to the array — in this example we just let the contents be same text for all items, but you can put a chart or some additional data here as well:
Integrate real data
Loading of the data from an API can be done with different libraries, and one such small and useful library is called Axios. Within the mounted lifecycle hook, we will add the call to the API, and wait for the promise to resolve.
Within the promise handler, we changed the array coinData to hold the freshly loaded data.
To make it working, we had to add an additional external script to the Codepen using the settings dialog:
Display most popular coin
Once the data is loaded, we usually want to show a single or a couple of tabs by default instead of all like it currently works after our last step. To do this, we will add a new array allCoinData to hold all of the downloaded data (as you can see, I have much imagination with variable names :)), and in the coinData we will hold only the coins shown in the tabs component. Vue.js will automatically refresh the list of displayed tabs whenever the coinData gets changed.
Here is the updated code which does what we just described:
Implement the search feature
To implement the search feature, we will replace the existing <v-text-field> with the <v-select> component and bind it to the list of coins we retrieved from API using items attribute. We defined name as the displayed item-text and added autocomplete attribute to enable typeahead functionality.
We have also used change event to detect when a user selected a coin. If he did select something, we call the addTab method. Which coin was selected is passed as a parameter of the function.
Other attributes were also used:
- class ma-4 adds a margin around the entry field
- solo-inverted and flat give the same look as it was with the <v-text-field>
Within the addTab method, we check if the coin is already in the list of selected ones, and if not, we push it to the end of array:
The beauty of Vue.js is that we only need to manipulate the variables and arrays in our application, and everything gets refreshed in the UI automatically.
After implementing the search feature, our tabs component looks like this:
Let’s make the percentage indicators a bit nicer — show them in red or green color depending on if they are positive or negative. Here we use standard Vue.js feature of class binding, and for the colors the built-in Vuetify classes for text colors:
As with any new feature or a functionality, errors can occur and the only way to find them is to test the finished work. The example from this article can be viewed at Codepen, so please feel free to click around and let me know in the comments if some bug got through!
Here is one last picture of the finished work, where we can see multiple tabs, arrows for currently not visible tabs and customised tab titles:
With this Part II of the article we have finished our coverage of the Tabs Component, and also touched functionality of some other components available in the Vuetify framework. We also demonstrated how to use Codepen to quickly make a proof of concept for a part of our UI which uses real data loaded from an external service using Axios library.
As we can see, although we are constrained a bit with the Material Design guidelines, there are ways to get around them and use excellent Vuetify components in different and interesting ways.