Comparing a Data Dashboard Building With React, Vue.js and Webix JS UI Library – Beragampengetahuan
Contents
Getting Started
We’ll use a demo app built with Webix Jet as a starting point. It’ll help us save some time since we won’t have to create the project structure for our solution manually. For example, we can download this jet-start demo from GitHub. It’ll give us a ready-to-use project structure, but there are some files we don’t actually need. Let’s delete everything from the views folder and create a new file named main.js inside. We’ll place all the code we need for building our dashboard’s side menu and header in this file. Now, we can start creating something.
Building the beragampengetahuan (React, Vue.js)
The configuration for the widgets we will use is written in the config() method of the TopView class. This method returns the interface of the component that will be initialized. We’ll start from the top of the dashboard’s beragampengetahuan and implement all the elements one by one.
Logo and Button

Let’s build it as a layout with two columns. The first column uses the template widget, a non-editable area usually used for rendering plain text or a single data record. In our case, it’ll contain a logo. The second column has an inner layout consisting of three rows. The first and third of these rows are empty spacer components, while the second one contains the button control:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
export default class TopView extends JetView { config() { const header = { css: ‘logo-and-button’, borderless: true, padding: { right: 20, bottom: 1 }, cols: [ { view: ‘template’, css: ‘logo’, template: `<img src=“ style=‘margin-top: -5px;’/>`, height: 68, }, { rows: [ {height: 20, css: ‘menu-background’}, { view: ‘button’, width: 28, height: 28, value: `<img src=${arrowButton} />`, css: ‘header-button’ }, {css: ‘menu-background’} ] } ] };
/* other components */ } } |
Admin Info

We’ll build this part of the dashboard solution using the template widget again. Notice that specifying the view type as “template” is optional in Webix, and the following code will work perfectly fine despite the differences with the previous example:
|
|
const adminInfo = { css: ‘admin’, height: 68, template: () => { return `<div class=‘tile’> <img src=“ /> <div style=‘margin-left: 10px’> <p class=“name”>Leslie Alexander</p> <p class=“job”>Administrator</p> </div> </div>`; } }; |
Hierarchical Menu

Here, we’ll use the beragampengetahuan widget from the Webix library. It allows for using menus with hierarchical structure in your software solutions. In the data property of the widget, we’ll pass data as an array of objects to be rendered as menu elements following the template described in the template property:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
const menu = { view: ‘beragampengetahuan’, id: ‘menu’, css: ‘menu’, layout: ‘y’, select: true, width: 260, template: ‘<img src=”#icon#” class=”beragampengetahuan-icon”> <span>#value#</span><img src=”#expand#” class=”expand-icon”/>’, data: [ { value: ‘Dashboard’, id: ‘dashboard’, icon: dashboardIcon, expand: ” }, { value: ‘Calendar’, id: ‘calendar’, icon: calendarIcon, expand: arrowButton }, { value: ‘Projects’, id: ‘projects’, icon: projectsIcon, expand: arrowButton }, { value: ‘Tasks’, id: ‘tasks’, icon: tasksIcon, expand: arrowButton }, { value: ‘Employees’, id: ‘employees’, icon: employeesIcon, expand: ” }, { value: ‘Customers’, id: ‘customers’, icon: customersIcon, expand: ” } ], on: { onBeforeSelect: (id) => { return id === ‘dashboard’; } } }; |
For navigation purposes, we’ll enable the menu within the init() method of the same class. This method specifies the component initialization behavior.
|
|
init() { this.use(plugins.Menu, ‘menu’); } |
Check out the documentation page to learn more about the Webix Jet menu plugin.
Buttons at the Bottom

Three elements in this part of the dashboard will differ only in text and icon. Therefore, we can create a new method that will generate the buttons:
|
|
generateButton(icon, text) { return {rows: [ { view: ‘button’, css: ‘bottom-buttons’, value: `<img src=${icon} class=“beragampengetahuan-icon” style=“margin-right: 11px”> <span>${text}</span>`, height: 30 }, {height: 20} ]}; } |
Next, we can describe the layout containing these buttons:
|
|
const bottomButtons = { rows: [ {css: ‘menu-background’}, this.generateButton(notificationsIcon, ‘Notifications’), this.generateButton(lightThemeIcon, ‘Light Theme’), this.generateButton(logoutIcon, ‘Log Out’), {height: 8} ] }; |
That’s it. The side menu for our software solution is ready!
Building the Dashboard Header
To build the dashboard header for our solution, we’ll need the template widget we’re already familiar with, the toolbar widget, and the tabbar widget. We’ll describe the layout consisting of three columns. The first two will contain the template widget with the required text. The third one will contain the tabbar widget working as a panel with clickable elements:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
const toolbar = { view: ‘toolbar’, height: 68, css: ‘toolbar’, cols: [ { type: ‘header’, template: ‘Dashboard’, css: ‘toolbar-header-left’, borderless: true }, { type: ‘header’, template: ‘Today’, css: ‘toolbar-header-right’, borderless: true }, { view: ‘tabbar’, value: ‘month’, borderless: true, css: ‘toolbar-tabbar’, optionWidth: 90, width: 270, options: [ { id: ‘month’, value: ‘Month’ }, { id: ‘week’, value: ‘Week’ }, { id: ‘day’, value: ‘Day’ } ] } ] }; |
That’s all the code we need to build the header for our solution.
Building the Dashboard Body
We can use previously created elements to describe the main page structure:
|
|
const main = { cols: [ { rows: [{ css: ‘beragampengetahuan’, rows: [header, adminInfo, {height: 6}, menu, bottomButtons] }] }, { rows: [ toolbar, { $subview: true } ] } ] };
return main; |
In this code, we can see the object that contains the following: $subview: true. Subview is a component that can be settled within other components. We’ll place all the content of our page inside it.
Now, inside the views folder, let’s create a new folder named dashboard, where we’ll place all the components of the dashboard body. Inside, create the index.js file where we’ll describe the page structure. It’ll include the layout widget with the space type that comprises three rows, each of which will have a similar component. The first and third rows will contain three columns. The second row will contain another row inside.
Thanks to the Menu plugin, for this solution, we can describe the inner content of these rows and columns as $subview: ‘file in the dashboard folder’. We can right away create files in the dashboard folder, each corresponding to the name of our solution’s component (e.g., projects.js, employees.js, customers.js, etc.):
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
import { JetView } from ‘webix-jet’;
export default class TopView extends JetView { config() { return { type: ‘space’, css: ‘dashboard-layout’, paddingY: 14, paddingX: 14, rows: [ { type: ‘space’, css: ‘dashboard-layout’, margin: 24, cols: [ { $subview: ‘dashboard.projects’ }, { $subview: ‘dashboard.employees’ }, { $subview: ‘dashboard.customers’ } ] }, { type: ‘space’, paddingY: 0, css: ‘dashboard-layout’, rows: [ { $subview: ‘dashboard.revenue’ } ] }, { type: ‘space’, css: ‘dashboard-layout’, margin: 24, cols: [ { $subview: ‘dashboard.dug’ }, { $subview: ‘dashboard.gas’ }, { $subview: ‘dashboard.oil’ } ] } ] }; } } |
Projects (React, Vue.js)

To build the Projects component of the dashboard solution, we’ll need the template widget and layout widget. In the projects.js file, let’s create a class Projects and describe the component header in its config() method:
|
|
export default class Projects extends JetView { config() { const header = { view: ‘template’, css: ‘header’, borderless: true, height: 24, template: ‘Projects’ }; } |
Using the template widget, we can describe the inner part of this dashboard component consisting of two blocks. The first one will contain the text with a number, and the second one will contain text and state strings built based on incoming data:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
const totalProjects = { view: ‘template’, borderless: true, localId: ‘projects’, css: ‘card-info’, minWidth: 448, template: (obj) => { const resultArray = []; const leftPart = `<div> <p class=‘quantity’>${obj.total}</p> <p class=‘title’>Total Projects</p> </div>`; if (obj.data) { obj.data.forEach(element => { resultArray.push(` <div class=”projects-state”> <span style=”width: 75px” class=”state”>${element.state}</span> <div class=‘progress-bar’> <div class=‘progress-bar-result’ style=“width: ${149 * element.amount / 100}px;”></div> </div> <span class=”state”>${element.amount}%</span> </div> `); }); } return ` ${leftPart} <div style=‘padding-top: 30px’> ${resultArray.join(”)} </div> `; } }; |
We’ll use the models folder to allow our solution to store the data. Inside the folder, we can create the projectData.js file with the following code:
|
|
const projectData = [ { id: 1, total: 43, data: [ { id: 2, state: ‘Agreement’, amount: 10 }, { id: 3, state: ‘Preparation’, amount: 24 }, { id: 4, state: ‘In Progress’, amount: 66 } ] } ];
export default projectData; |
Since all required parts of this dashboard component are ready, we can describe the overall structure and implement the data parsing functionality in the init() method. For this, use the following code in the projects.js file:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
const main = { css: ‘card’, padding: { top: 20, left: 24, right: 24 }, rows: [ header, { padding: { left: 24 }, rows: [ totalProjects ] } ] };
return main; }
init() { this.$$(‘projects’).parse(projectData); } } |
That’s how we build the Projects component.
Employees (React, Vue.js)

The Employees component also looks pretty similar, so the code looks pretty much the same: You can use the same approach for building the Customers components, making the required adjustments to ensure they fit our solution and display the data correctly.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
|
import { JetView } from ‘webix-jet’; import employeesData from ‘../../models/employeesData’;
export default class Employees extends JetView { config() { const header = { view: ‘template’, css: ‘header’, borderless: true, height: 24, template: ‘Employees’ };
const employees = { view: ‘template’, borderless: true, localId: ‘employees’, css: ‘card-info employees’, minWidth: 438, template: (obj) => { const array = []; if (Object.values(obj).length) { obj.data.forEach(element => { let icons = []; if (element.employeesIcons) { icons = element.employeesIcons.map((elem, index) => `<span class=${index > 4 ? ‘add-icon’ : ”}><img src=${elem} style=‘left: ${index * 19}px’/></span>`); } array.push(`<div style=‘position: relative’> <p class=‘quantity’>${element.total}</p> <p class=‘title’>${element.text}</p> <div class=‘block-with-icons’>${icons.join(”)}</div> </div>`); }); } return ` ${array.join(”)} `; } };
const main = { css: ‘card’, padding: { top: 20, left: 24, right: 24 }, height: 210, rows: [ header, { padding: { left: 12, right: 12 }, rows: [ employees ] } ] };
return main; }
init() { this.$$(‘employees’).parse(employeesData); } } |
Customers (React, Vue.js)

You can use the same approach for building the Customers components, making the required adjustments to ensure they fit our solution and display the data correctly.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
import { JetView } from ‘webix-jet’; import customersData from ‘../../models/customersData’;
export default class Customers extends JetView { config() { const header = { view: ‘template’, css: ‘header’, borderless: true, height: 24, template: ‘Customers’ };
const customers = { view: ‘template’, borderless: true, localId: ‘customers’, css: ‘card-info customers’, template: (obj) => { const array = []; const firstPart = `<div> <p class=‘quantity’>${obj.total}</p> <p class=‘title’>Total Customers</p> </div>`; if (Object.values(obj).length) { obj.data.forEach(element => { array.push(`<div style=‘display: flex’> <img src=“https://beragampengetahuan.com/blog/dashboard-building-with-react-vue-js-webix/${element.flag}”/> <p style=‘width: 100px’>${element.country}</p> <p class=‘proportion’>${element.proportion}%</p> </div>`); }); } return ` ${firstPart} <div class=‘all-countries’> ${array.join(”)} </div> `; } };
const main = { css: ‘card’, padding: { top: 20, left: 24, right: 24 }, height: 210, rows: [ header, { padding: { left: 46, right: 36 }, rows: [ customers ] } ] };
return main; }
init() { this.$$(‘customers’).parse(customersData); } } |
Revenue (React, Vue.js)
We can use the Webix chart widget to build the dashboard’s Revenue component. It can turn data into different chart types like line, spline, area, bar, pie, 3D-pie, donut, scatter, and radar.
Read Also Best JavaScript Libraries for Data Visualization (Featuring Webix and DHTMLX)
Let’s take a closer look at how this component displays the data:

As you can see, the top part contains a header that displays such data as the currently selected year and chart legend. We can build each of them using the template widget. Here’s the code from the revenue.js file that we need for this:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
const header = { view: ‘template’, css: ‘header’, borderless: true, height: 24, template: ‘Revenue’ };
const year = { view: ‘template’, css: ‘header year’, borderless: true, template: `<img src=“https://beragampengetahuan.com/blog/dashboard-building-with-react-vue-js-webix/${arrow}”/>2021<img src=“https://beragampengetahuan.com/blog/dashboard-building-with-react-vue-js-webix/${arrow}”/>` };
const legend = { view: ‘template’, css: ‘header legend’, borderless: true, template: ` <div> <span style=”background: ${colors.drilling}”></span> <p>Drilling</p> </div> <div> <span style=”background: ${colors.service}”></span> <p>Service</p> </div> <div> <span style=”background: ${colors.other}”></span> <p>Other</p> </div>` }; |
Next, we’ll use the chart widget with type: splineArea property to define the chart type that will be used for data visualization. Using xAxis and yAxis properties, we can define horizontal and vertical axes. We can add objects with value and color properties to describe our diagrams in the series property. According to the layout, we will use additional lines with the spline type to create the volumetric upper part of our diagram:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
|
const chart = { view: ‘chart’, localId: ‘revenue’, type: ‘splineArea’, css: ‘chart’, height: 389, alpha: 0.08, xAxis: { template: (num) => { return `<span>${num.month}</span>`; }, lines: false, lineColor: ‘#878595’, color: ‘#878595’ }, yAxis: { start: 0, end: 105, step: 20, template: (num) => { return num % 20 ? ” : `$${num}k`; }, lineColor: ‘#878595’, color: ‘#878595’ }, series: [ { value: ‘#drilling#’, color: colors.drilling }, { type: ‘spline’, value: ‘#drilling#’, item: { borderColor: ‘#FFFFFF’, color: colors.drilling, radius: (obj) => { return obj.month === ‘Oct’ ? 3 : 0; }, type: ‘r’ }, line: { color: colors.drilling } }, { value: ‘#service#’, color: colors.service }, { type: ‘spline’, value: ‘#service#’, item: { borderColor: ‘#FFFFFF’, color: colors.service, radius: (obj) => { return obj.month === ‘Oct’ ? 3 : 0; }, type: ‘r’ }, line: { color: colors.service } }, { value: ‘#other#’, color: colors.other }, { type: ‘spline’, value: ‘#other#’, item: { borderColor: ‘#FFFFFF’, color: colors.other, radius: (obj) => { return obj.month === ‘Oct’ ? 3 : 0; }, type: ‘r’ }, line: { color: colors.other } }, ] }; |
Finally, let’s gather all these components together:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
const main = { css: ‘card’, padding: { top: 20, left: 24, right: 24 }, rows: [ { cols: [ header, year, legend ] }, chart ] };
return main; |
DugMeters (React, Vue.js)

By implementing the DugMeters component, we start dealing with the dashboard elements’ bottom row. We can build it like the previous component using the Webix chart widget. However, our data type, in this case, differs from the previous example. Therefore, in this part of our solution, we can use the type: ‘bar’ property to use another chart type. Also, we can adjust the number of units being compared.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
|
import { JetView } from ‘webix-jet’; import { dugData, colors } from ‘../../models/revenueAndDugDatas’;
export default class Revenue extends JetView { config() { const header = { view: ‘template’, css: ‘header’, borderless: true, height: 24, template: ‘Dug Meters Per Day’ };
const legend = { view: ‘template’, css: ‘header legend’, borderless: true, template: ` <div> <span style=‘background: ${colors.service}’></span> <p>Service</p> </div> <div> <span style=”background: ${colors.other}”></span> <p>Other</p> </div>` };
const chart = { view: ‘chart’, localId: ‘dug’, type: ‘bar’, css: ‘chart’, preset: ‘stick’, xAxis: { template: (num) => { return num.day % 2 ? ”: `<span>${num.day} ${num.month}</span>`; }, lines: false, lineColor: ‘#878595’, color: ‘#878595’ }, yAxis: { start: 0, end: 105, step: 50, template: (num) => { return num % 50 ? ” : `${num}m`; }, lineColor: ‘#878595’, color: ‘#878595’ }, series: [ { value: ‘#service#’, color: colors.service }, { value: ‘#other#’, color: colors.other } ] };
const main = { css: ‘card’, padding: { top: 20, left: 24, right: 24 }, rows: [ { cols: [ header, legend ] }, chart ] };
return main; }
init() { this.$$(‘dug’).parse(dugData); } } |
GasProduced (React, Vue.js)

For this part of our solution, we’ll use the GeoChart widget. It allows us to display the data related to different countries using Google GeoChart. Also, we should not forget about the header and chart legend:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
const header = { view: ‘template’, css: ‘header’, borderless: true, height: 24, template: ‘Gas Produced in the Region’ };
const chart = { view: ‘geochart’, localId: ‘gas’, key: ‘AIzaSyAi0oVNVO-e603aUY8SILdD4v9bVBkmiTg’, css: ‘chart’, tooltip: ”, chart: { legend: ‘none’, colorAxis: { minValue: 0, maxValue: 2, colors: [‘#8D44B9’, ‘#4599BD’, ‘#6CB875’] }, backgroundColor: ‘#1F1F1F’, datalessRegionColor: ‘#39393D’, width: 301 } };
const legend = { view: ‘template’, localId: ‘geoLegend’, css: ‘header legend geo’, borderless: true, width: 131, template: (obj) => { const resultArray = []; if (obj.data) { obj.data.forEach(element => { resultArray.push(` <div> <span style=‘background: ${colors[element.selected]}’></span> <p>${element.value} m<sup>3</sup></p> </div> `); }); } return resultArray.join(”); } }; |
The last step is to combine all the parts to build the component we need:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
const main = { css: ‘card’, padding: { top: 20, left: 24, right: 24 }, rows: [ header, { cols: [ chart, { rows: [ {height: 50}, legend ] } ] } ] };
return main; |
OilProduced (React, Vue.js)

This component has many similarities with the previous one. It looks the same and works with similar data. This circumstance allows us to implement it like the Gas Produced component with some extra widget configs.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
|
import { JetView } from ‘webix-jet’; import { countries, oil, colors } from ‘../../models/gasAndOilDatas’;
export default class Oil extends JetView { config() { const header = { view: ‘template’, css: ‘header’, borderless: true, height: 24, template: ‘Oil Produced in the Region’ };
const chart = { view: ‘geochart’, localId: ‘oil’, css: ‘chart’, tooltip: ”, chart: { legend: ‘none’, colorAxis: { minValue: 0, maxValue: 2, colors: [‘#8D44B9’, ‘#4599BD’, ‘#6CB875’] }, backgroundColor: ‘#1F1F1F’, datalessRegionColor: ‘#39393D’, width: 301 } };
const legend = { view: ‘template’, localId: ‘geoLegend’, css: ‘header legend geo’, borderless: true, width: 131, template: (obj) => { const resultArray = []; if (obj.data) { obj.data.forEach(element => { resultArray.push(` <div> <span style=‘background: ${colors[element.selected]}’></span> <p>${element.value} bbls<sup></sup></p> </div> `); }); } return resultArray.join(”); } };
const main = { css: ‘card’, padding: { top: 20, left: 24, right: 24 }, rows: [ header, { cols: [ chart, { rows: [ {height: 50}, legend ] } ] } ] };
return main; }
init() { this.$$(‘oil’).parse(countries); this.$$(‘geoLegend’).parse(oil); } } |
That’s all we need to build the dashboard.
rencana pengembangan website
metode pengembangan website
jelaskan beberapa rencana untuk pengembangan website, proses pengembangan website, kekuatan dan kelemahan bisnis pengembangan website
, jasa pengembangan website, tahap pengembangan website, biaya pengembangan website
#Comparing #Data #Dashboard #Building #React #Vue.js #Webix #Library