<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Serhii Pylypchuk</title>
    <description>The latest articles on DEV Community by Serhii Pylypchuk (@serhiipylypchuk1991).</description>
    <link>https://dev.to/serhiipylypchuk1991</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F684667%2F47f41256-9c42-4f14-8c0e-488cc1e94a0c.jpeg</url>
      <title>DEV Community: Serhii Pylypchuk</title>
      <link>https://dev.to/serhiipylypchuk1991</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/serhiipylypchuk1991"/>
    <language>en</language>
    <item>
      <title>Webix Gantt Chart. Handy web tool for efficient project management</title>
      <dc:creator>Serhii Pylypchuk</dc:creator>
      <pubDate>Wed, 13 Apr 2022 04:05:03 +0000</pubDate>
      <link>https://dev.to/serhiipylypchuk1991/webix-gantt-chart-handy-web-tool-for-efficient-project-management-14no</link>
      <guid>https://dev.to/serhiipylypchuk1991/webix-gantt-chart-handy-web-tool-for-efficient-project-management-14no</guid>
      <description>&lt;p&gt;In a previous article on one of the most popular Agile approaches, I introduced you to such a Japanese project management tool as &lt;a href="https://dev.to/serhiipylypchuk1991/webix-kanban-a-modern-implementation-of-the-agile-philosophy-5ef"&gt;"Kanban"&lt;/a&gt;. And today I'm going to move from the far east to the far west part of the world. In this publication, you will learn about the "Gantt" method, its history and modern implementations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;The first prototype of the so-called "Gantt Chart" was invented, oddly enough, by the Polish engineer &lt;a href="https://en.wikipedia.org/wiki/Karol_Adamiecki"&gt;Karol Adamecki&lt;/a&gt; back in 1896. He developed a fundamentally new approach for visualizing and analyzing interrelated processes in production (steelmaking) and successfully used it in practice. Later, he named his invention the "harmonogram".&lt;/p&gt;

&lt;p&gt;Since Adametsky published only in Russian and Polish, his work was not widely known in English-speaking countries. But in 1910, another American engineer, &lt;a href="https://en.wikipedia.org/wiki/Henry_Gantt"&gt;Henry Gantt&lt;/a&gt;, introduced his own analogue of a similar system in the United States. He used his invention to track the time that factory workers spent on the current tasks.&lt;/p&gt;

&lt;p&gt;Subsequently, these two systems were combined into the solution we now know as "Gantt Chart".&lt;/p&gt;

&lt;h2&gt;
  
  
  Application
&lt;/h2&gt;

&lt;p&gt;So, let's find out what kind of tasks can be covered using Gantt Chart. Generally, such a system allows one to solve several issues related to project management at once. &lt;/p&gt;

&lt;p&gt;First of all, you will be able to plan each stage of the project with well-defined start and end dates of the workflow.&lt;/p&gt;

&lt;p&gt;Besides, the Gantt Chart allows you to identify milestones, the most important events of the project. And thanks to the development of software, the Adamecki-Gantt chart allows you to track the progress of tasks, link dependent tasks, manage resources and costs, and improve collaboration between team members. But it was not always so.&lt;/p&gt;

&lt;h2&gt;
  
  
  Development
&lt;/h2&gt;

&lt;p&gt;For a long time, such diagrams were drawn on paper by hand. As a consequence of any change to the graph, the entire diagram had to be redrawn. &lt;/p&gt;

&lt;p&gt;Later, project managers started using paper tapes and special rectangles to indicate the columns of the chart. This approach made the analysis process significantly faster. The reason was that the key elements could be freely moved, rather than redrawing the diagrams again and again.&lt;/p&gt;

&lt;p&gt;In a modern management environment, no one uses hand drawing for such analysis anymore. If you ask Uncle Google about the digital analogues of the Gantt Chart, the browser will show you a lot of ready-made apps, both paid and free. They will more than cover the basic needs of the average project manager.&lt;/p&gt;

&lt;p&gt;But what if you are faced with the task to implement such a system in your own application? The answer is simple - you need to look not for a static app, but for a flexible widget that can be used both independently and as a plug-in.&lt;br&gt;&lt;br&gt;
In this article, I want to talk about one of such widgets. Next, we will dive into the JavaScript Gantt Chart developed by the Webix team. Let's see what it is and what its advantage is.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is Webix Gantt Chart
&lt;/h2&gt;

&lt;p&gt;Webix Gantt is a comprehensive JavaScript solution for Agile project management. In short, the widget functionality allows working with projects of any complexity, scheduling tasks and tracking their progress, marking important workflow milestones, managing resources, and much more. In fact, you can find all this functionality in the vast majority of such kinds of apps.&lt;/p&gt;

&lt;p&gt;To save your time, I will skip the detailed description of trivial things related to the functionality. After all, if you are reading this article, you already have some idea of ​​​​the basic principles of working with Gantt Charts. But if you still want to refresh your knowledge, you can find all the information you need in the appropriate &lt;a href="https://docs.webix.com/gantt__userguide.html"&gt;guide&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Now let's take a closer look at the benefits of the Gantt Chart widget and its configurations.&lt;/p&gt;
&lt;h2&gt;
  
  
  Advantages
&lt;/h2&gt;

&lt;p&gt;On the Internet, you can find a lot of ready-made applications and services that allow you to create Gantt Charts and use them to manage your projects. But the weak side of such tools is their static state. &lt;/p&gt;

&lt;p&gt;If we are talking about desktop apps, they need to be installed and used locally. When using the corresponding online services, you need to share all your data with a third-party resource. This approach is more flexible, but it doesn't look safe.&lt;/p&gt;

&lt;p&gt;In both cases, you are limited to the initial functionality that was laid down by the developers of the respective products. The other side of the coin is that you need to use only 10 of the 100 features proposed. In this case, you have no way to shed the "extra ballast." And this, in turn, will affect the app's performance.&lt;/p&gt;

&lt;p&gt;So now let's dive into the advantages of a similar solution offered to us by the Webix team. Based on the fact that Gantt Chart is a web application written in JavaScript and CSS, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use the widget as a separate app, or integrate it as a third-party module (with React, Angular, and other frameworks)&lt;/li&gt;
&lt;li&gt;flexibly configure the component, by adding only features that cover your project needs&lt;/li&gt;
&lt;li&gt;customize the appearance and behavior of the component, not limited to the basic functionality&lt;/li&gt;
&lt;li&gt;use the ready-made &lt;a href="https://github.com/webix-hub/gantt-node"&gt;Node.js&lt;/a&gt; and &lt;a href="https://github.com/webix-hub/gantt-go"&gt;Go&lt;/a&gt; backend, or connect your custom one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you don't see clear advantages in all I have mentioned above, and the flexibility of settings is not a priority for you, then you should look for another tool. As a variant, you can look at the &lt;a href="https://ganttpro.com/ru/"&gt;GanttPro&lt;/a&gt; service.&lt;/p&gt;

&lt;p&gt;The next part of the article is for those who think out of the box and are not limited to certain templates. I will tell you more about how to initialize, configure, customize, and localize the &lt;em&gt;Gantt Chart&lt;/em&gt; widget.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to Create a Widget with Basic Functionality
&lt;/h2&gt;

&lt;p&gt;Let's start with the fact that &lt;em&gt;Gantt Chart&lt;/em&gt; is an advanced extension of the Webix library. To use the widget, include the library resources first, and then the corresponding &lt;em&gt;.js&lt;/em&gt; and &lt;em&gt;.css&lt;/em&gt; files of the widget itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- Webix resources --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"codebase/webix.js"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"codebase/webix.css"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- Gantt Chart resources --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"codebase/gantt.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"codebase/gantt.css"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After including the required scripts, you need to call the widget's constructor. To start executing the app code only after the page is fully loaded, pass it to the &lt;code&gt;webix.ready(…)&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
      &lt;span class="cm"&gt;/*Gantt Chart constructor*/&lt;/span&gt;
      &lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gantt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;your_backend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, to initialize the widget you only need to write a few lines of code. Now you can create and manage your projects using a convenient interface and basic functionality.&lt;/p&gt;

&lt;p&gt;A few more words about licensing. Like other complex widgets, Gantt Chart depends on the Webix core and is distributed with the Pro version of the library.&lt;/p&gt;

&lt;p&gt;You can &lt;a href="https://webix.com/gantt/download.html"&gt;download&lt;/a&gt; the trial Pro version with all complex widgets, which is free for 30 days. This will allow you to try all the benefits and flexibility of working with the Gantt Chart in practice. And after this, you can decide whether this tool is right for you or not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring
&lt;/h2&gt;

&lt;p&gt;Webix Gantt Chart is a kind of constructor. It consists of several components of the core library. Each of them includes an API with which you can customize the appearance and behavior of certain parts of the interface. Besides, the widget has a set of its own configurations.&lt;/p&gt;

&lt;p&gt;It is worth clarifying here that you can configure the widget using the simplest and most convenient JSON syntax. All you need is to set the necessary properties to the appropriate values. Let's look at some of the configurations in detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connecting to Backend
&lt;/h3&gt;

&lt;p&gt;To start working with your projects, you need to load the corresponding data. In a real case, the data will be stored on a remote server. When initializing the app, you should specify a link to the server script (your own or one of two solutions available on our github). Gantt will load your project data and send all changes back to the server if needed. &lt;/p&gt;

&lt;p&gt;To connect Gantt Chart to the backend, use the &lt;code&gt;url&lt;/code&gt; property. Read more about working with the server side in the corresponding article.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;view:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gantt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="err"&gt;url:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_backend"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;link&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;script&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Linking Tasks
&lt;/h3&gt;

&lt;p&gt;Each project may include a huge number of additional tasks. Each of these tasks may directly depend on the readiness of other tasks. To visualize such dependencies, the widget provides special lines that allow you to link the tasks to each other.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8Xcw2456--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2727kevbhzaorutq53kg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8Xcw2456--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2727kevbhzaorutq53kg.png" alt="Linking Tasks" width="687" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This kind of linking is supported by default. To switch it off, you need to set the &lt;code&gt;links&lt;/code&gt; property to &lt;code&gt;false&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;view:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gantt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;links:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Critical Path
&lt;/h2&gt;

&lt;p&gt;Each project has certain time frames. To meet the deadline, it is necessary to complete each of the tasks timely and consistently.&lt;/p&gt;

&lt;p&gt;To analyze the project deadline, the widget provides a special &lt;strong&gt;critical path&lt;/strong&gt;. It allows you to display a chain of tasks that need to be completed on time to meet project deadlines.&lt;/p&gt;

&lt;p&gt;Gantt Chart analyzes only the tasks with the &lt;strong&gt;"end-to-start"&lt;/strong&gt; links. If the schedules of such tasks are overlapped or set without considering the margin of time (and real life can be unforeseeable), the widget will consider them critical and highlight in red.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cVRPVQ5T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5z5abqcs7fmj8wnlobvb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cVRPVQ5T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5z5abqcs7fmj8wnlobvb.png" alt="Critical path" width="687" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To show the critical path, you need to set the &lt;code&gt;criticalPath&lt;/code&gt; property to &lt;code&gt;true&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;view:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gantt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;criticalPath:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Split Tasks
&lt;/h3&gt;

&lt;p&gt;Besides the links between different tasks, you can also create related subtasks within a specific task. The parts of a split task will be displayed in one row and connected to each other by a dotted line. &lt;/p&gt;

&lt;p&gt;Unlike the basic tasks, subtasks of a split task are not displayed in the tree and cannot include nested items.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vb-M5tNh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pojlg2qns21m6cupbecw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vb-M5tNh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pojlg2qns21m6cupbecw.png" alt="Split tasks" width="687" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To enable split tasks, you need to set the &lt;code&gt;split&lt;/code&gt; property to &lt;code&gt;true&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;view:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gantt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;split:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Working with Resources
&lt;/h3&gt;

&lt;p&gt;One of the distinguishing features of &lt;em&gt;Webix Gantt&lt;/em&gt; is the ability to work with resources. You can efficiently manage resources by assigning them to certain project tasks. You will also be able to view resources in the tree and chart using a special mode, as well as analyze the workload of resources via a special diagram. &lt;/p&gt;

&lt;p&gt;To enable the resources support, you need to set the &lt;code&gt;resources&lt;/code&gt; property to &lt;code&gt;true&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;view:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gantt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="err"&gt;url:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_backend"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;resources:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The widget will load the required data by the specified url. After this, the users will be able to manage the corresponding resources via a suitable editor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d7lkeJtd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dfw0l6rtgkqzt9ixdx43.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d7lkeJtd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dfw0l6rtgkqzt9ixdx43.png" alt="Resources" width="687" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources View Mode
&lt;/h3&gt;

&lt;p&gt;By default, the widget displays only the tasks in the tree and chart. In this way, you can view the projects, tasks and subtasks, as well as milestones (significant project events).&lt;/p&gt;

&lt;p&gt;But you can switch to the resources view mode as well. In this mode, the widget displays only the tasks grouped by resources they are assigned to. There is also a separate &lt;em&gt;Unassigned&lt;/em&gt; section that contains all the unassigned tasks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Gz8DfQzn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sfvgok9too6kgok0sykf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Gz8DfQzn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sfvgok9too6kgok0sykf.png" alt="Resources view mode" width="687" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To enable the resources view mode, you need to set the &lt;code&gt;display&lt;/code&gt; property to a &lt;code&gt;"resources"&lt;/code&gt; value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;view:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gantt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;resources:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;required&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;string!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;display:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"resources"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Resources Diagram
&lt;/h3&gt;

&lt;p&gt;Besides the view mode, you can also display resources on a special diagram. It allows you to analyze the workload of each resource by hours and tasks for each work day. If the resource limit is exceeded, the Gantt will highlight it in red on the diagram.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vkZLjkjx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nhngwbe1r881psfpq4dk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vkZLjkjx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nhngwbe1r881psfpq4dk.png" alt="Resources diagram" width="687" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To display the resources diagram, you need to enable the resources support and set the &lt;code&gt;resourcesDiagram&lt;/code&gt; property to &lt;code&gt;true&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;view:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gantt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;url:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_backend"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;resources:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;required&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;string!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;show&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;diagram&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;under&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;chart&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;resourcesDiagram:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the sections above, I described only a small part of all the Gantt Chart settings. You can find the full list of widget configurations in the corresponding &lt;a href="https://docs.webix.com/gantt__configuring.html"&gt;article&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customization
&lt;/h2&gt;

&lt;p&gt;Besides configuring via the built-in settings, you have an ability to customize almost any part of the interface and its behavior. But for this, you need to understand what is going on under the hood of Gantt Chart. &lt;/p&gt;

&lt;p&gt;The structure of the widget is built as a SPA application based on the &lt;em&gt;MV&lt;/em&gt; pattern of the &lt;strong&gt;Webix Jet&lt;/strong&gt; framework. In this case the interface (&lt;em&gt;View&lt;/em&gt;) is separated from the business logic (&lt;em&gt;Model&lt;/em&gt;). Each of the interface elements is a separate component of the Webix library (&lt;em&gt;button, select, toolbar&lt;/em&gt;, and others).&lt;/p&gt;

&lt;p&gt;Significant parts of the interface (&lt;em&gt;tree, chart,&lt;/em&gt; and others) are stored in separate classes inherited from the &lt;em&gt;JetView&lt;/em&gt; class. And the business logic, which is a model, is also stored separately in the form of modules. In the context of framework, these modules are called services. &lt;/p&gt;

&lt;p&gt;To customize the interface and logic of the app, all you need to do is get a PhD in programming and then dig into the widget code a bit :) And even for this, you need to know at least the key principles of working with the &lt;em&gt;Webix Jet&lt;/em&gt; framework. &lt;/p&gt;

&lt;p&gt;Read the "&lt;a href="https://webix-ui.medium.com/webix-jet-framework-through-the-eyes-of-a-freshman-part-1-composition-and-navigation-60976f86d74a"&gt;&lt;strong&gt;Webix Jet framework through the eyes of a freshman&lt;/strong&gt;&lt;/a&gt;" article to find out the basic principles of working with the framework, or refer to the &lt;a href="https://webix.gitbook.io/webix-jet/"&gt;documentation&lt;/a&gt; for more detailed information.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Customize the Interface
&lt;/h3&gt;

&lt;p&gt;And now let's move on to the customization itself. As I mentioned above, each element of the interface is a separate component of the Webix library. Each significant part of the interface is a class that consists of these components. You can easily change, add, or completely remove any part of the interface.&lt;/p&gt;

&lt;p&gt;Let's imagine that you have to add an extra column to the task tree. First, you need to create a new &lt;code&gt;CustomTree&lt;/code&gt; class by inheriting it from the class that stores the task tree interface settings (&lt;code&gt;gantt.views.tree&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;In this case, we are going to use the &lt;code&gt;config()&lt;/code&gt; method included into all non abstract classes of the widget. This method defines a module view. To change the module interface, you need to override either the &lt;code&gt;config()&lt;/code&gt; or &lt;code&gt;init()&lt;/code&gt; methods. The common rule works in the following way: if you are sure that all changes in the UI don't break the inner logic, you can use the &lt;code&gt;config()&lt;/code&gt; method. Otherwise, you need to use the &lt;code&gt;init()&lt;/code&gt; one.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;config()&lt;/code&gt; lifecycle method is inherited from the &lt;code&gt;JetView&lt;/code&gt; class. It is responsible for customizing the part of the interface that you want to change.&lt;/p&gt;

&lt;p&gt;Inside this method, you should get the configuration object of the new class. It corresponds to the configurations of the &lt;code&gt;treetable&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;After this, you can add a new column template into the array of the &lt;code&gt;columns&lt;/code&gt; property and return the new settings. In code, it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;CustomTree&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;gantt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tree&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ui&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// get config object of treetable&lt;/span&gt;
    &lt;span class="c1"&gt;// add a new column template&lt;/span&gt;
      &lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;progress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#progress#%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="c1"&gt;// return new settings&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, you need to replace the class you inherited with the one you created. This can be done using the &lt;code&gt;override&lt;/code&gt; property in the widget constructor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;view:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gantt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;url:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://docs.webix.com/gantt-backend/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;override:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Map(&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="err"&gt;gantt.views.tree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;CustomTree&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a simple way to change the interface of Gantt Chart. To learn more about the widget customization, refer to its &lt;a href="https://docs.webix.com/gantt__customization.html"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Localization
&lt;/h2&gt;

&lt;p&gt;The ease of localization is one of the nice bonuses of the Gantt widget. By default, all the interface labels are displayed in English. But you can easily create several custom locales and switch between them.&lt;/p&gt;

&lt;p&gt;To translate labels in a particular language, you should create a separate locale and specify the necessary translations there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;gantt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locales&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ua&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Add task&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Добавити завдання&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Add project&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Добавити проект&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="err"&gt;…&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the locale with custom translations is ready, you should apply it to the entire app. This can be done using the &lt;code&gt;locale&lt;/code&gt; property in the widget constructor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;id:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gantt_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;view:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gantt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;url:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_backend"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;locale:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;lang:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ua"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to create an international app, you should provide several locales and switch between them dynamically. To do this, you need to access the &lt;strong&gt;locale&lt;/strong&gt; service of the &lt;em&gt;Jet&lt;/em&gt; framework using its &lt;code&gt;getService()&lt;/code&gt; method. After this, call the &lt;code&gt;setLang()&lt;/code&gt; method of the locale service. It takes the name of the locale to be applied as a parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gantt_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;getService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;locale&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setLang&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* your locale */&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ua, en, ru, custom_one &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the widget is distributed only with the English locale by default. But the library provides a special place where users can post custom locales as well. These translations can be found on the &lt;a href="https://github.com/webix-hub/locales/tree/master/gantt"&gt;webix-hub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, I introduced you to the Webix Gantt widget and its main features. As you can see, it is a very functional and flexible component in terms of configuration and customization. Among other things, you can integrate it with any framework or library. To find more information about the capabilities and settings of Gantt Chart, refer to the widget &lt;a href="https://docs.webix.com/desktop__gantt.html"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>management</category>
      <category>webix</category>
    </item>
    <item>
      <title>Webix Kanban. A Modern Implementation of the Agile Philosophy</title>
      <dc:creator>Serhii Pylypchuk</dc:creator>
      <pubDate>Tue, 28 Dec 2021 12:25:26 +0000</pubDate>
      <link>https://dev.to/serhiipylypchuk1991/webix-kanban-a-modern-implementation-of-the-agile-philosophy-5ef</link>
      <guid>https://dev.to/serhiipylypchuk1991/webix-kanban-a-modern-implementation-of-the-agile-philosophy-5ef</guid>
      <description>&lt;p&gt;I think that each competent project manager heard about a system of the "flexible" approaches to software development. It is about the "&lt;a href="https://wikipedia.org/wiki/Agile_Manifesto"&gt;Agile methodologies&lt;/a&gt;" based on the values ​​of the "Agile Manifesto" and the 12 principles that underlie it.&lt;/p&gt;

&lt;p&gt;Kanban is one of the most popular approaches to implementing agile principles in software development (and not only). It assumes discussion of the problems in real time and full transparency of all work processes. &lt;/p&gt;

&lt;p&gt;All tasks are displayed on a special Kanban board. It is used to visualize, analyze and optimize the workflow. This approach allows the team members to check the status of each individual task at any stage of development. Besides, you will be able to assess the progress of the project as a whole.&lt;/p&gt;

&lt;p&gt;In this article, I want to tell you about one of the complex widgets of the Webix library, which implements the key principles of the kanban approach. We'll talk about such a project management tool as &lt;strong&gt;JavaScript Kanban&lt;/strong&gt; and discuss its key features. Let's figure out how everything works.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Webix Kanban
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Webix Kanban Board&lt;/strong&gt; is a convenient and intuitive tool for managing "agile projects". Using this component you can visualize and track your team's workflows, as well as monitor the specific project tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;p&gt;The widget operating principle is based on special cards arranged in columns and rows on the Kanban board. Each card is a separate task with a specific name, description of details, assigned performers, deadlines, and other equally important attributes. Each column represents a certain stage of the readiness of a particular task.&lt;/p&gt;

&lt;p&gt;Using this approach, the technical and service teams can understand how much work they need to take on. They can do the assigned tasks while adhering to the principles of continuous improvement.&lt;/p&gt;

&lt;p&gt;It's worth noting that Webix Kanban is fully written in JavaScript and CSS. You can easily determine the appearance of the board and its structure. You will also be able to customize the widget for the specific features of your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Functionality
&lt;/h3&gt;

&lt;p&gt;The widget has a fairly large set of flexibly customizable features. They'll help you to manage the team's workflow more efficiently, taking into account even the smallest nuances. &lt;/p&gt;

&lt;p&gt;In particular, you can manage the tasks (kanban cards) in the following way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create, edit, copy, and delete tasks &lt;/li&gt;
&lt;li&gt;move tasks between columns (thus changing their status)&lt;/li&gt;
&lt;li&gt;set tags and the priority of task execution&lt;/li&gt;
&lt;li&gt;assign responsible users&lt;/li&gt;
&lt;li&gt;customize and style the card content &lt;/li&gt;
&lt;li&gt;sort and filter the tasks according to certain parameters&lt;/li&gt;
&lt;li&gt;add images to cards, attach extra files and discuss nuances in the comments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The widget interface is also configurable quite flexibly. You can create any number of tasks and distribute them into the corresponding columns, as well as define the internal structure for each of them. Below I will talk about this in detail.&lt;/p&gt;

&lt;p&gt;If the built-in functionality isn't enough for you, you can create a custom one using special templates. They allow you to configure both the app interface and its behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Kanban with Initial Functionality
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;JavaScript Kanban&lt;/strong&gt; is one of the complex widgets of the Webix library. It can be purchased along with the Pro version of the library, as a part of one of the licensed packages. Details can be found on the &lt;a href="https://webix.com/kanban/#licensing"&gt;licensing&lt;/a&gt; page.&lt;/p&gt;

&lt;p&gt;You can assess in practice all the advantages and flexibility of working with Kanban (and not only). For this, you need to &lt;a href="https://webix.com/kanban/download.html"&gt;download&lt;/a&gt; the trial Pro version of the library. It includes all complex widgets and is available free for 30 days. &lt;/p&gt;

&lt;p&gt;Now let's see how to include the required sources and initialize the widget on a regular HTML page. &lt;/p&gt;

&lt;p&gt;Considering that Kanban is built on the Webix components, to initialize it you should first include the main library sources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Webix --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"codebase/webix.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"codebase/webix.css"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, you need to specify the corresponding paths to the &lt;strong&gt;.js&lt;/strong&gt; and &lt;strong&gt;.css&lt;/strong&gt; files of the Kanban Board.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Kanban Board --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"codebase/kanban.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"codebase/kanban.css"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After including the necessary sources, you can initialize the widget. To do this, you should call the &lt;code&gt;webix.ui()&lt;/code&gt; constructor, by passing an object with the necessary configurations as a parameter.&lt;/p&gt;

&lt;p&gt;To make sure that the widget code starts executing after the page is fully loaded, call the widget constructor inside the &lt;code&gt;webix.ready(function(){/* a widget constructor */})&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
      &lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanban&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;:[...],&lt;/span&gt; 
        &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cards_data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can use the basic functionality of the Kanban and further customize it as you see fit. In the browser you may see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lIOKbzab--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hcdxmyhasurgqql9ehbg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lIOKbzab--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hcdxmyhasurgqql9ehbg.png" alt="Initial Kanban" width="708" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Kanban
&lt;/h2&gt;

&lt;p&gt;Kanban Board, like many other complex Webix widgets, is a kind of layout constructor. It can be made up of several separate components. Each of them has its own methods and properties. With their help, you can customize the interface elements and their behavior.&lt;/p&gt;

&lt;p&gt;Besides the internal API, the widget has built-in parameters. They allow you to configure the component and manage its functionality. It would not hurt to remind you that you need to use a declarative approach to set the Webix widgets. It means that all properties and their values ​​are specified in a regular JSON object.&lt;/p&gt;

&lt;p&gt;The component itself is declared via the &lt;code&gt;view: "kanban"&lt;/code&gt; expression. After this, you should specify the column parameters the kanban cards will be placed into, as well as the corresponding data for each task. These are the minimum settings required for the widget to start.&lt;/p&gt;

&lt;p&gt;Now let's see how to set some more advanced configurations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layout Structure
&lt;/h3&gt;

&lt;p&gt;Webix Kanban is a kind of layout app. You can define any suitable structure you need, guided only by the project requirements and common sense :). The widget allows you to create as many cards and columns as you want to manage your team's tasks more effectively. Let's take a look at several quite possible options of the Kanban Board layout for your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Progress columns
&lt;/h3&gt;

&lt;p&gt;Traditionally, any Kanban board should consist of at least 3 columns, which are used to determine the status of project tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backlog&lt;/strong&gt; - scheduled tasks &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In progres&lt;/strong&gt;s - tasks in progress&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Done&lt;/strong&gt; - completed tasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To configure the Kanban columns, you need to understand the basic principles of building the &lt;a href="https://docs.webix.com/api__refs__ui.layout.html"&gt;Webix layouts&lt;/a&gt;. In particular, Kanban has a special &lt;a href="https://docs.webix.com/api__ui.baselayout_cols_config.html"&gt;&lt;code&gt;cols&lt;/code&gt;&lt;/a&gt; property for working with columns. In the array of this parameter, you can set the desired configurations for each column.&lt;/p&gt;

&lt;p&gt;The layout of the above-mentioned structure will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Backlog&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanbanlist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;In Progress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanbanlist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;work&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Done&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanbanlist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;done&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For each column, you can specify a header via the &lt;code&gt;header&lt;/code&gt; property and its general settings in the object of the &lt;code&gt;body&lt;/code&gt; property. Here you should define the desired structure for displaying cards by setting the &lt;code&gt;view&lt;/code&gt; property to one of the following parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"kanbanlist"&lt;/strong&gt; - cards in columns are arranged as a list (see &lt;a href="https://snippet.webix.com/xdy80vi5"&gt;live demo&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"kanbandataview"&lt;/strong&gt; - depending on a free space, the cards in columns are arranged as a list, which can consist of several rows (see &lt;a href="https://snippet.webix.com/ac4uhxth"&gt;live demo&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;custom option&lt;/strong&gt;. You can split your list by adding a new layout with columns/rows or use &lt;strong&gt;tabview&lt;/strong&gt; to switch through the lists (see &lt;a href="https://snippet.webix.com/iv0pfg4p"&gt;live demo&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To distribute the cards into corresponding columns, you need to specify a special key via the &lt;code&gt;status&lt;/code&gt; property. The same key needs to be stored in the card data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Column headers
&lt;/h3&gt;

&lt;p&gt;Kanban provides an option to define a stylish and functional header for any desired column. To implement this, you need to use such an entity as &lt;strong&gt;kanbanheader&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;The standard header collapses when clicking on the corresponding column (as an accordion). The &lt;strong&gt;kanbanheader&lt;/strong&gt; allows you to add new cards and can be displayed with a specific style. The layout of a column with such a header will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// column parameters&lt;/span&gt;
      &lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt; 
            &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanbanheader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// declare the kanbanheader component&lt;/span&gt;
            &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Backlog&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// define the header title&lt;/span&gt;
            &lt;span class="na"&gt;link&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// bind the header to the list via its status&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sub&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// add a compact styling&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt; 
            &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// define the list ID &lt;/span&gt;
            &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanbanlist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// declare the kanbanlist component&lt;/span&gt;
            &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// set the list status&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To add cards, use the round icon next to the header name.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dWM_gEKK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h6jzrggkf0snis98g3ew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dWM_gEKK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h6jzrggkf0snis98g3ew.png" alt="Headers" width="706" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://snippet.webix.com/0nv4ujea"&gt;Live demo&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Nested columns
&lt;/h3&gt;

&lt;p&gt;Such a layout system allows you to create a structure of any complexity and nesting level. For example, in one of the columns, you can create nested columns, which can contain some extra columns. See an example below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZMj7wBwP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lk4asw4f51u91uehks0r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZMj7wBwP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lk4asw4f51u91uehks0r.png" alt="Nested columns" width="708" height="489"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://snippet.webix.com/iaqxhi9r"&gt;Live demo&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Swimlanes
&lt;/h3&gt;

&lt;p&gt;Let's say you are engaged in software development. The teams of designers and programmers are working tirelessly on your project to make it successful. To separate the area of ​​responsibility of each team, you can add corresponding sections to the desired kanban columns.&lt;/p&gt;

&lt;p&gt;To implement these swimlanes in the Kanban Board, you need to set the &lt;code&gt;status&lt;/code&gt; property to a complex value.&lt;/p&gt;

&lt;p&gt;For example, let's see how to add such sections to the "In progress" and "Done" columns. It helps you to see what tasks designers and programmers are involved in at the current time, and what tasks have already been completed. The layout structure will be as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;...,&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;In progress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanbanheader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Development&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sub&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanbanlist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;work&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;team&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanbanheader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Design&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sub&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanbanlist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;work&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;team&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Done&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanbanheader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Development&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sub&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanbanlist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;done&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;team&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanbanheader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Design&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sub&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanbanlist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;done&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;team&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;cards_data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To define the column swimlanes, you need to specify its &lt;code&gt;status&lt;/code&gt; property to the complex value. Besides the status itself, you can also specify the key of the corresponding team (Development or Design) via the &lt;code&gt;team&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;The same keys should be specified in the data object of each card:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cards_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;work&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;team&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Kanban tutorial&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;work&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;team&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;New skin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;done&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;team&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sidebar options&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,...&lt;/span&gt;  &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;done&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;team&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Toolbar controls&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="c1"&gt;// other data&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the browser you will see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kfs3_hXc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2krth7i4nrvgc22ni8ba.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kfs3_hXc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2krth7i4nrvgc22ni8ba.png" alt="Swimlanes" width="708" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://snippet.webix.com/rcw5ag2m"&gt;Live demo&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Card Parameters
&lt;/h3&gt;

&lt;p&gt;And now let's talk about the kanban cards, which intend to manage tasks on your project. Each card can contain a different set of elements depending on its data and the widget parameters.  &lt;/p&gt;

&lt;p&gt;Besides the task name, you can specify the following elements for the card:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tags&lt;/li&gt;
&lt;li&gt;priority &lt;/li&gt;
&lt;li&gt;comments &lt;/li&gt;
&lt;li&gt;assigned performers&lt;/li&gt;
&lt;li&gt;attached files.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tags
&lt;/h3&gt;

&lt;p&gt;There are cases when a task relates to several internal projects or requires using certain technologies. To keep track of such nuances, you can mark the tasks with special tags and then filter cards by them (if necessary).&lt;/p&gt;

&lt;p&gt;To create tags, you need to specify the &lt;code&gt;tags&lt;/code&gt; property in the configuration object and set it to an array with the corresponding data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanban&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...,&lt;/span&gt;
  &lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;                      
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JavaScript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;   
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PHP&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;     
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Python&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C++&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;      
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cards_data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the card data you need to set the &lt;code&gt;tags&lt;/code&gt; property to an array with the IDs of the required tags:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cards_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Task 1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;work&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Task 2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the browser you will see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Lz4MB8Ug--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eai622bxg2oi50gi956j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Lz4MB8Ug--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eai622bxg2oi50gi956j.png" alt="Tags" width="707" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also specify tags in the card data directly. In this case, they will not be displayed in the card editor and you will not be able to delete or change them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Priority
&lt;/h3&gt;

&lt;p&gt;To meet the project deadline, it is very important to prioritize the tasks. Webix Kanban makes it possible with the vertical colored lines on the left edge of the cards.&lt;/p&gt;

&lt;p&gt;Let's suppose you want to divide the priority of tasks into three levels of urgency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;high&lt;/strong&gt; - red line&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;normal&lt;/strong&gt; - green line&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;low&lt;/strong&gt; - orange line.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To do this, set the &lt;code&gt;colors&lt;/code&gt; property to an array with data objects for each color:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Urgent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;                                 
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Normal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Low&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;orange&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;    
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cards_data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also specify the initial priority of each card by setting the required color in its data object via the &lt;code&gt;color&lt;/code&gt; property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cards_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Task 1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;orange&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;work&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Task 2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;done&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Task 3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the browser you will see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gSfUolDp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/whav6c1i21ojey2166jz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gSfUolDp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/whav6c1i21ojey2166jz.png" alt="Priority" width="707" height="142"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Comments
&lt;/h3&gt;

&lt;p&gt;Your project may include the tasks in which several specialists take part at once. For an efficient collaboration of all participants of such tasks, the widget provides an ability to write comments.&lt;/p&gt;

&lt;p&gt;To enable commenting, you should set the &lt;code&gt;comments&lt;/code&gt; property to &lt;code&gt;true&lt;/code&gt;. If you need to display comments just after the widget initializing, specify the corresponding data in the array of the &lt;code&gt;comments&lt;/code&gt; property of the card data object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cards_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Task 1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2018-06-14 23:01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No worry, just wait&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2018-06-14 22:01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ok, I'm waiting&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt; 
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;work&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Task 2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;done&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Task 3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the browser you will see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4jrDd-w4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6mm7clh2ur094t4411gy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4jrDd-w4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6mm7clh2ur094t4411gy.png" alt="Comments" width="707" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Assignments
&lt;/h3&gt;

&lt;p&gt;You can assign an employee to work on each task. It is worth noting here that the widget has a limit on the number of assignments. Based on this, you can assign only one performer to one task.&lt;/p&gt;

&lt;p&gt;To add employees into your project, in the widget configuration object you need to specify the &lt;code&gt;users&lt;/code&gt; property and set it to the array with the data of the corresponding users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Margaret Atwood&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imgs/matwood.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Fannie Flagg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imgs/fflagg.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Irvine Welsh&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imgs/iwelsh.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can assign workers to the particular task via the card editor. But there is an easier way. To assign users directly in the card, you should specify the &lt;code&gt;userList: true&lt;/code&gt; expression in the configuration object.&lt;/p&gt;

&lt;p&gt;In the browser you will see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---29SBW6---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y05vrfedqlqv91szmvot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---29SBW6---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y05vrfedqlqv91szmvot.png" alt="Assignments" width="707" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Attachments
&lt;/h3&gt;

&lt;p&gt;Sometimes there are situations when you need to attach the additional files to the card. It can be a detailed instruction or a picture with an interface design. The widget allows you to attach such files via the card editor.&lt;/p&gt;

&lt;p&gt;To implement it, you should specify a path to the script for uploading files via the &lt;code&gt;attachments&lt;/code&gt; property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanban&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;attachments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server/upload&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...,&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cards_data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a card editor, you will see a special interface for uploading files. The already uploaded items will be displayed at the bottom of the editor. The number of the attached elements will be displayed on the card.&lt;/p&gt;

&lt;p&gt;You can display the initial attachments just after the widget initializes. To do this, provide the corresponding data in the array of the &lt;code&gt;attachments&lt;/code&gt; property in the card data object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cards_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Task 1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;attachments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;link&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./server/files/image001.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;85919&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;link&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./server/files/image002.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;105981&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the browser you will see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KGIgj46i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/isfk8xj9redqjkhd0j1x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KGIgj46i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/isfk8xj9redqjkhd0j1x.png" alt="Attachments" width="707" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Card operations
&lt;/h3&gt;

&lt;p&gt;You can perform some operations with a card via its context menu, namely: open an editor, copy or delete a card. The menu icon is not displayed by default. To show it, specify the &lt;code&gt;cardAction: true&lt;/code&gt; expression in the configuration object.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wzHMeGT4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oz9g752l3sbvhsokj947.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wzHMeGT4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oz9g752l3sbvhsokj947.png" alt="Card operations" width="707" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also define the custom operations with cards. Read more about this in the corresponding &lt;a href="https://docs.webix.com/api__ui.kanban_cardactions_config.html"&gt;documentation article&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Card Editor
&lt;/h2&gt;

&lt;p&gt;The parameters of any kanban card can be changed using a special editor. It opens when you double-click on the card or click on the edit icon.&lt;/p&gt;

&lt;p&gt;By default, the editor is disabled. To enable it, you should set the &lt;code&gt;editor&lt;/code&gt; property to &lt;code&gt;true&lt;/code&gt;. The editor fields will depend on the widget settings. For example, if you specify the &lt;code&gt;tags&lt;/code&gt;, &lt;code&gt;users&lt;/code&gt;, &lt;code&gt;attachments&lt;/code&gt; and &lt;code&gt;colors&lt;/code&gt; properties in the configuration object, the corresponding fields will appear in the editor. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FwCgnfeQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fdwnoux5fxllmlhk16y9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FwCgnfeQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fdwnoux5fxllmlhk16y9.png" alt="Card Editor" width="532" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also change the order of the built-in fields or create custom ones. For this, you need to define them in the array of the &lt;code&gt;editor&lt;/code&gt; property. It should be noted that the names of the controls must match the names of the properties of the Kanban data items.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Task&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;multicombo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tags&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;richselect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
         &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;China Mieville&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
         &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Helen Walsh&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
         &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jeff Noon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read more about the editor customization in the corresponding &lt;a href="https://docs.webix.com/kanban__adding_items.html#nastroykaredaktora"&gt;documentation article&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Loading Data
&lt;/h2&gt;

&lt;p&gt;In the widget settings you can specify an array of the card's data that you want to display during initialization. Depending on where the data are stored (client or server), you can use either the &lt;code&gt;data&lt;/code&gt; or &lt;code&gt;url&lt;/code&gt; properties, as well as the &lt;code&gt;parse()&lt;/code&gt; or &lt;code&gt;load()&lt;/code&gt; methods. Let's take a closer look at each of these approaches.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parsing Client-Side Data
&lt;/h3&gt;

&lt;p&gt;Like any other Webix widget, Kanban accepts data in the JSON format by default. If the data are stored on the client side, you can parse it in two ways: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;via the &lt;code&gt;data&lt;/code&gt; property in the widget's constructor &lt;/li&gt;
&lt;li&gt;via the &lt;code&gt;parse()&lt;/code&gt; method. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The data object should contain the fields in which you need to describe certain parameters of the card.&lt;/p&gt;

&lt;p&gt;Each data element requires a unique ID. Besides, you can specify a set of the following parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;status&lt;/strong&gt; - a status of the element, which defines a card's belonging to the corresponding column (required parameter)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;text&lt;/strong&gt; - a title of the element (task)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;tags&lt;/strong&gt; - a comma-separated list of tags or an array of their IDs ( if data for tags are presented in a separate data set)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$list&lt;/strong&gt; - an index of the list, the element will be placed into&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;comments&lt;/strong&gt; - a list of comments or an array of their IDs (if the comments data are stored in a separate data set)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;color&lt;/strong&gt; - a priority color &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;user_id&lt;/strong&gt; - an ID of the user the task is assigned to&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;attachments&lt;/strong&gt; - a list of files attached to the card.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A card data object may look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cards_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;in progress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Performance tests&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tags&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$list&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;comments&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#FE0E0E&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;attachments&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;link&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./server/files/image001.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;85919&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;link&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./server/files/image002.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;105981&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;{...}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can set the &lt;code&gt;data&lt;/code&gt; property to this object in the widget constructor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanban&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cards_data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or parse data via the &lt;code&gt;parse()&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanban&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanban_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanban_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cards_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Loading Server-Side Data
&lt;/h3&gt;

&lt;p&gt;If you want to load server data, you need to set &lt;code&gt;url&lt;/code&gt; property to the path to the required file or script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanban&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cards_data.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or you can call the &lt;code&gt;load()&lt;/code&gt; method, by passing a path to the file as a parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanban&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanban_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanban_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cards_data.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here it should be borne in mind that the widget can take data in various formats. For example, if you want to load data in XML format, you should specify this format directly via the &lt;code&gt;datatype&lt;/code&gt; property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanban&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanban_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cards_data.xml&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;datatype&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;xml&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or pass it to the &lt;code&gt;load()&lt;/code&gt; method as a second parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kanban_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cards_data.xml&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;xml&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Kanban Localization
&lt;/h2&gt;

&lt;p&gt;A significant advantage of all Webix widgets is the ease of its localization. By default, all Kanban labels are displayed in English. But you have an opportunity to change the current locale before the widget initialization or create a custom one. In the object of the custom locale you can specify the labels in the language you need. Let's take a look at both of these options.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Modify the Current Locale
&lt;/h3&gt;

&lt;p&gt;The labels of the current locale are stored in the &lt;strong&gt;webix.i18n.kanban&lt;/strong&gt; object. You can specify the needed translations for the following elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;buttons and labels in the card editor&lt;/li&gt;
&lt;li&gt;options in the context menu.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The current locale object has the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;i18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kanban&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;copy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Copy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dnd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Drop Files Here&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remove&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Remove&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;save&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Save&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;confirm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The card will be deleted permanently, are you sure?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;editor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;add&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Add card&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;edit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Edit card&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;assign&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Assign to&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;attachments&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Attachments&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;head&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Editor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tags&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tags&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;upload&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Upload&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;menu&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;copy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Copy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;edit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Edit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remove&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Remove&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to modify the labels of the current locale, you should specify the corresponding values in the &lt;strong&gt;webix.i18n.kanban&lt;/strong&gt; object. The widget will change them in the interface. &lt;/p&gt;

&lt;h3&gt;
  
  
  How to Create a Custom Locale
&lt;/h3&gt;

&lt;p&gt;In the second option, you need to create a new locale with a similar structure via the &lt;code&gt;webix.i18n.locales[localeN].kanban&lt;/code&gt; expression. In this object you can set the corresponding keys to the new translations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;i18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locales&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ru-RU&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;kanban&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;copy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Копировать&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dnd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Бросайте файлы сюда&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remove&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Удалить&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;save&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Сохранить&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;confirm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Вы собираетесь навсегда удалить эту карточку. Вы уверены?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;editor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;add&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Добавить карточку&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;edit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Редактировать карточку&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// other labels&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="c1"&gt;// other labels&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To apply a new locale, you need to call the &lt;code&gt;setLocale()&lt;/code&gt; method of the &lt;strong&gt;webix.i18n&lt;/strong&gt; object before the widget initialization. It takes an object with translations as a parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;i18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setLocale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ru-RU&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://snippet.webix.com/kmtwpl9g"&gt;Live demo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, I have tried to introduce you to the JavaScript Kanban widget, its main usage and functionality. As you can see, it is a very functional and highly customizable component. You can easily integrate it with any framework or library you need, as well as connect to the backend.&lt;/p&gt;

&lt;p&gt;​​This publication covers only a small part of all the widget's capabilities. To learn more about configuring and customizing JS Kanban, visit its &lt;a href="https://docs.webix.com/desktop__kanban_board.html"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>agile</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Webix SpreadSheet. Is it a full-fledged web alternative to Excel?</title>
      <dc:creator>Serhii Pylypchuk</dc:creator>
      <pubDate>Fri, 24 Sep 2021 15:53:10 +0000</pubDate>
      <link>https://dev.to/serhiipylypchuk1991/webix-spreadsheet-is-it-a-full-fledged-web-alternative-to-excel-56p0</link>
      <guid>https://dev.to/serhiipylypchuk1991/webix-spreadsheet-is-it-a-full-fledged-web-alternative-to-excel-56p0</guid>
      <description>&lt;p&gt;Continuing &lt;a href="https://dev.to/serhiipylypchuk1991/webix-file-manager-a-worthy-web-counterpart-of-a-desktop-application-62i"&gt;the topic of the gradual transition from desktop software to similar online services&lt;/a&gt;, in this publication I want to talk about a SpreadSheet widget that can compete with &lt;em&gt;his majesty "Excel"&lt;/em&gt;. It is an outstanding JavaScript component that provides full-fledged support of any spreadsheets. Meanwhile, this tool is very flexible and can be easily integrated into any environment.&lt;/p&gt;

&lt;p&gt;If you need to add some Excel-like tool with extensive functionality and high performance in your business application, you should pay attention to the &lt;strong&gt;SpreadSheet&lt;/strong&gt; widget from the Webix team. Let's figure out what they can offer to us and whether the game is worth the candle.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is JS Spreadsheet
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Webix SpreadSheet&lt;/strong&gt; is a comprehensive JavaScript solution for working with spreadsheets of varying complexity. The component is one of the most advanced tools from the complex widgets line of the Webix library.&lt;/p&gt;

&lt;p&gt;Recently (&lt;em&gt;starting with version 8.2&lt;/em&gt;), SpreadSheet has received a new engine and multi-sheet math support. These updates significantly accelerated its performance in comparison to previous versions.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Widget Functionality
&lt;/h3&gt;

&lt;p&gt;The tool functionality is quite extensive. You can create spreadsheets, manage their data via the user-friendly interface, export data in the required format (&lt;em&gt;Excel, PDF, CSV&lt;/em&gt; or &lt;em&gt;PNG&lt;/em&gt;), and much more. Besides creating your own sheets, you are able to import local data in Excel format and change them depending on your needs.&lt;/p&gt;

&lt;p&gt;In particular, you can work with the tables in this way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create, copy and delete sheets&lt;/li&gt;
&lt;li&gt;export, import and print sheets&lt;/li&gt;
&lt;li&gt;manage the history of changes&lt;/li&gt;
&lt;li&gt;stylize the cell contents&lt;/li&gt;
&lt;li&gt;sort, filter and block the cell contents&lt;/li&gt;
&lt;li&gt;add links, pictures, charts and comments into cells and above them&lt;/li&gt;
&lt;li&gt;manage columns and rows:

&lt;ul&gt;
&lt;li&gt;add and remove&lt;/li&gt;
&lt;li&gt;hide and show&lt;/li&gt;
&lt;li&gt;resize and freeze&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;apply a wide range of formulas and much more.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;As you can see, the widget's features are large enough and its abilities are not inferior to its desktop counterpart. To read more information about the SpreadSheet capabilities visit the &lt;a href="https://webix-guides.gitbook.io/spreadsheet-user-guide/" rel="noopener noreferrer"&gt;related article&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Widget Interface
&lt;/h3&gt;

&lt;p&gt;You can work with the widget via a convenient and user-friendly interface. If you are an experienced Excel user, you won't have any difficulties with understanding the component UI. Visually, it consists of 3 parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Toolbar&lt;/li&gt;
&lt;li&gt;Workspace&lt;/li&gt;
&lt;li&gt;Bottom bar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Toolbar contains different controls divided by functional groups. With their help, you can manage the sheet data. Depending on the widget settings, the controls may differ. But we'll talk about it later.&lt;/p&gt;

&lt;p&gt;On the workspace of the component, you can look through the spreadsheets you will work with. Using the toolbar controls, you can manage table data and change them on your own.&lt;/p&gt;

&lt;p&gt;And at the bottom part of the application, there is a Bottom bar where you can navigate through the sheets, as well as add, delete and rename them.&lt;/p&gt;

&lt;p&gt;Now after a brief overview of the widget functionality and interface, let's proceed to how to actually create one with a basic configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Create the Widget with Basic Functionality
&lt;/h2&gt;

&lt;p&gt;Webix SpreadSheet is one of the &lt;a href="https://webix.com/widget/complex-widgets/" rel="noopener noreferrer"&gt;most advanced tools&lt;/a&gt; of the Webix library. The widget is distributed under the Pro version of the library but isn't included in it. You can purchase this component as a part of the license package. Learn more on  the &lt;a href="https://webix.com/spreadsheet/#licensing" rel="noopener noreferrer"&gt;licensing page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to check all the advantages and flexibility of working with SpreadSheet (and not only), &lt;a href="https://webix.com/filemanager/download.html" rel="noopener noreferrer"&gt;download&lt;/a&gt; the trial Pro version of the library. It includes all complex widgets and is available for free for 30 days.&lt;/p&gt;

&lt;p&gt;Now let's see how to include the widget on the page and run it with basic functionality. And this is done ​​in a clear and straightforward way. Considering that SpreadSheet is based on the Webix components, you should first include the library sources. And after that, you need to specify the corresponding links to the &lt;em&gt;.js&lt;/em&gt; and &lt;em&gt;.css&lt;/em&gt; files of the widget itself. In code it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- Webix Library --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"codebase/webix.js"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"codebase/webix.css"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- SpreadSheet --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"codebase/spreadsheet.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"codebase/spreadsheet.css"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After including the required sources, you can initialize the widget with a few lines of code. To do this, you should call the &lt;code&gt;webix.ui()&lt;/code&gt; constructor, passing it an object with the required configuration.&lt;/p&gt;

&lt;p&gt;To make sure that the application code will start executing after the HTML page is fully loaded, put the constructor into the &lt;code&gt;webix.ready(function(){ /* constructor */ })&lt;/code&gt; method. In the code it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&gt;SpreadSheet&lt;/span&gt; &lt;span class="nx"&gt;Constructor&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spreadsheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;some_data_link&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can use the basic features of the SpreadSheet widget. And it is worth mentioning here that you have the ability to customize the component functionality. For instance, you can add the necessary tools or remove unnecessary ones. In the browser you will see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmwgtoqmc0x2jia9xqbv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmwgtoqmc0x2jia9xqbv.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Configure SpreadSheet
&lt;/h2&gt;

&lt;p&gt;The SpreadSheet widget is a kind of constructor. Its peculiarity lies in the fact that it consists of many separate Webix components. Each of them has its own properties and methods. Using these API you can customize one or another element of the interface and its behavior (for example, controls on the toolbar).&lt;/p&gt;

&lt;p&gt;Besides, the component itself has a rich set of its own properties and methods that allow you to customize it and manage its behavior. And it is worth clarifying here that you need to use a declarative approach to configure the Webix widgets. It means that all parameters are specified using a most convenient &lt;em&gt;JSON&lt;/em&gt; syntax. All you have to do is to set the required properties to corresponding values.&lt;/p&gt;

&lt;p&gt;The widget itself is declared via the &lt;code&gt;view:"spreadsheet"&lt;/code&gt; expression. And in fact, this is quite enough for creating a SpreadSheet with basic functionality. Now let's see how to enhance its configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extra Toolbar
&lt;/h3&gt;

&lt;p&gt;We can start with the app toolbar, which includes controls for managing tables. And it is worth noting here that in the default configuration, the toolbar displays only the minimal set of controls required for working with data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftyu32hwkpgi233bz9hoh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftyu32hwkpgi233bz9hoh.png" alt="Default Toolbar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to use an extended set of controls, you need to specify the &lt;code&gt;toolbar&lt;/code&gt; property and set it to the &lt;em&gt;"full"&lt;/em&gt; value. In the code it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spreadsheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;toolbar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;full&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the browser you will see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faocqe2uyikbpqqc2re2x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faocqe2uyikbpqqc2re2x.png" alt="Full Toolbar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are also cases when the toolbar is not needed at all. To remove it, set the &lt;code&gt;toolbar&lt;/code&gt; property to &lt;em&gt;false&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Top Menu
&lt;/h3&gt;

&lt;p&gt;Working with the extended toolbar may not always be convenient. It is also worth considering that if you have a small screen resolution, some of the controls can be hidden. To avoid this, you can add an additional menu at the top of the widget. To do this, you need to specify the &lt;code&gt;menu&lt;/code&gt; property and set it to &lt;em&gt;true&lt;/em&gt; in the component configuration. In the code it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spreadsheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;menu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in the browser you will see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz049lodpp4si07qid5wg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz049lodpp4si07qid5wg.png" alt="Top Menu"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Formula Editor
&lt;/h3&gt;

&lt;p&gt;As it was mentioned above the widget's functionality is not inferior to its desktop elder brother. The proof of this is the full support of all formulas for working with data that are supported in Excel. You can find a complete list of formulas with a detailed description in &lt;a href="https://docs.webix.com/spreadsheet__functions.html#vstroennyefunkcii" rel="noopener noreferrer"&gt;this&lt;/a&gt; article.&lt;/p&gt;

&lt;p&gt;And for working with formulas there is a special editor that is located under the toolbar. When you enter the function name, the editor will show a list of possible options that correspond to the entered characters. Besides, when you click on a cell the formula is applied to, the widget will highlight all cells that are within the range of  this formula.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6df9lheuh64gkf60t0s1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6df9lheuh64gkf60t0s1.png" alt="Formula Editor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Optionally, you can hide this editor and math support will remain the same. To do this, you should set the &lt;code&gt;liveEditor&lt;/code&gt; property to &lt;em&gt;false&lt;/em&gt; in the widget constructor. In the code it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spreadsheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;liveEditor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bottom Bar
&lt;/h3&gt;

&lt;p&gt;If you are supposed to work with several files at once, you should activate the bottom bar of the widget, which is hidden by default. With its help you can create new sheets as well as navigate through existing ones.&lt;/p&gt;

&lt;p&gt;If you want to show this panel, set the &lt;code&gt;bottombar&lt;/code&gt; property to &lt;em&gt;true&lt;/em&gt;. In the code it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spreadsheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;bottombar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the browser, you will see the following result: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fel87sqjerdc69w6u32a7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fel87sqjerdc69w6u32a7.png" alt="Bottom Bar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It should also be borne in mind that if you are using the extended version of the toolbar (&lt;code&gt;toolbar:"full"&lt;/code&gt;), the bottom bar will be displayed by default. To hide it, set the &lt;code&gt;bottombar&lt;/code&gt; property to &lt;em&gt;false&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ReadOnly Mode
&lt;/h3&gt;

&lt;p&gt;Sometimes there are situations where you need to use the widget only to display certain information. For such cases, the widget provides a readonly mode.&lt;/p&gt;

&lt;p&gt;To enable this feature, set the &lt;code&gt;readonly&lt;/code&gt; property to &lt;em&gt;true&lt;/em&gt;. Now the widget will display only the workspace with the current sheet (table). All additional panels will be hidden. In the code it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spreadsheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;readonly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the browser you will see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F860v13xnr8d3vzbcya1v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F860v13xnr8d3vzbcya1v.png" alt="Readonly Mode"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Loading Data
&lt;/h2&gt;

&lt;p&gt;In the widget configuration, you can specify the data to be displayed when initial loading. Depending on the data is located (on the client- or server-side), you should use either the &lt;code&gt;data&lt;/code&gt; or &lt;code&gt;url&lt;/code&gt; properties or the &lt;code&gt;parse()&lt;/code&gt; or &lt;code&gt;load()&lt;/code&gt; methods. Let's take a closer look at each of these options.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parsing Client-Side Data
&lt;/h3&gt;

&lt;p&gt;By default, the widget accepts data in &lt;em&gt;JSON&lt;/em&gt; format. If the data is on the client-side, you can either set the &lt;code&gt;data&lt;/code&gt; property to the object with data or parse the same data through the &lt;code&gt;parse()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;The data object will contain certain fields in which you can describe corresponding parameters, namely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;data (cell data)&lt;/li&gt;
&lt;li&gt;styles (cell styling)&lt;/li&gt;
&lt;li&gt;spans (cell fusion)&lt;/li&gt;
&lt;li&gt;table (table parameters)&lt;/li&gt;
&lt;li&gt;and other fields.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find a complete list of sheet settings in &lt;a href="https://docs.webix.com/spreadsheet__loading_data.html#formatzagruzkidannyh" rel="noopener noreferrer"&gt;this&lt;/a&gt; article. The object with settings may look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sheet_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;styles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wss1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;;;center;;;;;;;;;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sizes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;125&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Report - July 2016&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wss1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wss2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spans&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can set the &lt;code&gt;data&lt;/code&gt; property to this object in the widget constructor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spreadsheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sheet_data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or pass it to the &lt;code&gt;parse()&lt;/code&gt; method as a parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spreadsheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sheet_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see a live demo &lt;a href="https://snippet.webix.com/k97n3bb0" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Loading Server-Side Data
&lt;/h3&gt;

&lt;p&gt;If you need to load the remote data from the server, you can set the &lt;code&gt;url&lt;/code&gt; property to the corresponding path the desired file is located:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spreadsheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sheet_data.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or load the data via the &lt;code&gt;load()&lt;/code&gt; method, passing the corresponding link as a parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spreadsheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sheet_data.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it should be borne in mind here that the widget can handle data in various formats. For example, if you need to load data in &lt;em&gt;CSV&lt;/em&gt; format, you should set the &lt;code&gt;datatype&lt;/code&gt; property to the required format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spreadsheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sheet_data.csv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;datatype&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;csv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or pass the format to the &lt;code&gt;load()&lt;/code&gt; method as the second parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sheet_data.csv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;csv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see a live demo &lt;a href="https://snippet.webix.com/rkjwih02" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Loading data in Excel format requires special attention. Besides the data type and file path, you need to specify the &lt;code&gt;binary-&amp;gt;&lt;/code&gt; proxy object through which the data will be loaded. In the code it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spreadsheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;binary-&amp;gt;sheet_data.xlsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;datatype&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;excel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or in the same way via the &lt;code&gt;load()&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;binary-&amp;gt;sheet_data.xlsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;excel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see a live demo &lt;a href="https://snippet.webix.com/bcxa96nw" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Saving Data
&lt;/h2&gt;

&lt;p&gt;The SpreadSheet widget is a fully client-side app. But it also has a special API for working with a server. I have mentioned some of them in the previous section about loading server data.&lt;/p&gt;

&lt;p&gt;In addition, you have the ability to specify the path to the server script the &lt;em&gt;AJAX&lt;/em&gt; requests will be sent to (via the &lt;em&gt;POST&lt;/em&gt; method). It will happen when you make any sheet changes.&lt;/p&gt;

&lt;p&gt;To do this, you should set the &lt;code&gt;all&lt;/code&gt; property to the server script path in the object of the save property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spreadsheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server/get_data.php&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;save&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see a live demo &lt;a href="https://snippet.webix.com/zr3zwisk" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Now, if you change the sheet, all its data (including the state of the widget) will be automatically sent to the server. And for cases when you need to configure sending requests on certain actions with sheets (adding, renaming, updating or deleting data), you can set &lt;em&gt;RESTful&lt;/em&gt; saving.&lt;/p&gt;

&lt;p&gt;To track the sheet changes, you should subscribe to the &lt;em&gt;onChange&lt;/em&gt; event and set it to the handler. This can be done in the &lt;code&gt;on&lt;/code&gt; property object. Inside this handler, you can set up separate requests for each operation that will be sent automatically when some operation will be executed. The widget code with the event handler will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server/get_data.php&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spreadsheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;server_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
      &lt;span class="nl"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;oldName&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;update&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ajax&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;server_url&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;serialize&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rename&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ajax&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;server_url&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;oldName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remove&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ajax&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;del&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;server_url&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;insert&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ajax&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;server_url&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see a live demo &lt;a href="https://snippet.webix.com/ufrvr74h" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is how you can configure the information saving on the server. It is worth mentioning that the widget is distributed along with &lt;a href="https://github.com/webix-hub/spreadsheet-nodejs-demo/tree/save-all" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; backend. You can easily adapt it to any database you need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Localization
&lt;/h2&gt;

&lt;p&gt;One of the significant advantages of all Webix widgets is the ease of localization. And it is worth clarifying here that by default all widget labels are specified in English (the &lt;em&gt;en-US&lt;/em&gt; locale). But you can modify the current locale or create a custom one. Let's take a look at both of these options.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Change Current Locale
&lt;/h3&gt;

&lt;p&gt;All translations of the interface elements of the current locale are stored in the &lt;strong&gt;webix.i18n.spreadsheet&lt;/strong&gt; object. You can localize the following interface elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;all labels on the toolbar&lt;/li&gt;
&lt;li&gt;tooltips&lt;/li&gt;
&lt;li&gt;all menu items.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The locale object has the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;common&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Common&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;currency&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Currency&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;tooltips&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Font color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;background&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Background color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;menus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remove-sheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Remove sheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rename-sheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Rename sheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;math-error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#ERROR!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Math-ref-error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#REF!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;liveEditor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;edit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Edit:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;formats&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dateFormat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mm/dd/yyyy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;timeFormat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hh:mm AM/PM&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All you need to do is replace the current values ​​with your custom translation, and the widget will change them in the interface. As you can see, everything is pretty simple here.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Create Custom Locale
&lt;/h3&gt;

&lt;p&gt;In the second approach, you should create a custom locale with an identical structure and apply it to the entire widget. To do this, you need to add the corresponding translation to the &lt;strong&gt;webix.i18n.locales[localeN].spreadsheet&lt;/strong&gt; object and specify it some name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;i18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locales&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en-RU&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;spreadsheet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;labels&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;common&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;General&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;currency&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Currency&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tooltips&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Text color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;background&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Background color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To apply the new locale, you should call the &lt;code&gt;setLocale()&lt;/code&gt; method of the webix.i18n object, passing it the custom locale name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;i18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setLocale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ru-RU&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see a live demo &lt;a href="https://snippet.webix.com/nl2k3lc7" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;This method is more preferable because you have an ability to switch to the original locale at any time.&lt;/p&gt;

&lt;p&gt;It is also worth mentioning here that the library has a special platform where users can post their translations. You can check them out in &lt;a href="https://github.com/webix-hub/locales" rel="noopener noreferrer"&gt;this&lt;/a&gt; GitHub repository.&lt;/p&gt;

&lt;p&gt;You can also take part in the widget localization and upload your custom locale to the corresponding repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customization
&lt;/h2&gt;

&lt;p&gt;If the basic settings are not enough for you, you have the ability to customize the widget interface and functionality. And for this, you need to dig a little in the widget code. Let's look at some related samples of customizing the interface and functionality.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Add Extra Toolbar
&lt;/h3&gt;

&lt;p&gt;For instance, you can put any components between the toolbar and  workspace, as well as customize their behavior. To do this, you need to use the &lt;code&gt;subbar&lt;/code&gt; property. You may set it to either a specific component or a layout with several components. &lt;/p&gt;

&lt;p&gt;For clarity, let's add an extra toolbar with buttons for exporting data in various formats (&lt;em&gt;Excel, PNG, PDF&lt;/em&gt; and &lt;em&gt;CSV&lt;/em&gt;). To make it more convenient, you can save the toolbar constructor into a separate variable. You should set the &lt;code&gt;subbar&lt;/code&gt; property to this variable in the widget configuration. In the code it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;extra_toolbar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;toolbar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;css&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;webix_ssheet_toolbar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="na"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Export to Excel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
 &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
      &lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toExcel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Export to PNG&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
      &lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toPNG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Export to PDF&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
      &lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toPDF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;autowidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Export to CSV&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
      &lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toCSV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}},&lt;/span&gt;
    &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spreadsheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;subbar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;extra_toolbar&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see a live demo &lt;a href="https://snippet.webix.com/xucxevy9" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As you have already noticed, the library provides special methods for exporting data, which takes only the widget's ID. The data will be downloaded in the required format after clicking on the corresponding button on the extra toolbar. In the browser, you will see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fscqqf6j3prcg69gkzlir.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fscqqf6j3prcg69gkzlir.png" alt="Extra Toolbar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Customize Top Menu
&lt;/h3&gt;

&lt;p&gt;The widget configuration allows you to customize its top menu. For clarity, let's see how to remove some options and add new ones. &lt;/p&gt;

&lt;p&gt;First, you need to create an array with options of the top menu. For convenience, you can store it into a separate variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;custom_menu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;file&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;submenu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;excel-import&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;excel-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;custom-options&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;span class='custom_option'&amp;gt;Custom Options&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;submenu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;option-a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Option A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;option-b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Option B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;option-c&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Option C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code above, the first element of the array defines the built-in &lt;strong&gt;File&lt;/strong&gt; option. Its  drop-down list of options are responsible for importing and exporting data in Excel format. And the second element is a &lt;strong&gt;Custom Options&lt;/strong&gt; item with a drop-down list of arbitrary options.&lt;/p&gt;

&lt;p&gt;Now you should set the &lt;code&gt;menu&lt;/code&gt; property to the object which is stored in a variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spreadsheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;menu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;custom_menu&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in the browser you will see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5bw67y8nfirn6dkifxdk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5bw67y8nfirn6dkifxdk.png" alt="Custom Top Menu"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Customize Main Toolbar
&lt;/h3&gt;

&lt;p&gt;The widget toolbar consists of blocks, inside which there are buttons grouped by certain functions. You can manage these blocks (hide, show or add new ones), as well as customize the buttons inside the blocks. &lt;/p&gt;

&lt;p&gt;To modify the toolbar blocks, you need to use the &lt;code&gt;buttons&lt;/code&gt; property, which refers to the &lt;em&gt;buttons&lt;/em&gt; collection. This collection contains block names as keys and arrays with button names as values. For example, you can customize the current toolbar and include only 2 built-in blocks, as well as add a new block with a custom button. In the code it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spreadsheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;buttons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;undo-redo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;undo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;redo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;format&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;format&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Extra Block&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Custom Button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in the browser you will see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flwh927mkas4euf5c0szi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flwh927mkas4euf5c0szi.png" alt="Custom Main Toolbar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To define a custom toolbar, you need to use the toolbar property (which refers to the toolbar collection) to the object with the corresponding settings. Inside this object, you should form your custom toolbar structure (according to the principle of the layout building), set its sizes, indents, styles, and others. Read more about the toolbar customizing in the &lt;a href="https://docs.webix.com/spreadsheet__ui_guide.html" rel="noopener noreferrer"&gt;related article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can see a live demo &lt;a href="https://snippet.webix.com/wfgn2g9z" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, you learned about the SpreadSheet widget and its main features. In fact, this publication covers only the tip of the iceberg of all the possibilities that the tool has. As you can see, it is a very functional and flexible component. You can easily set, customize and integrate it with any framework or library you need. You also have the ability to set up interaction with the backend. To read more information about the possibilities and customization follow the widget &lt;a href="https://docs.webix.com/desktop__spreadsheet.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>spreadsheet</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Webix File Manager. A worthy web counterpart of a desktop application</title>
      <dc:creator>Serhii Pylypchuk</dc:creator>
      <pubDate>Wed, 18 Aug 2021 12:02:36 +0000</pubDate>
      <link>https://dev.to/serhiipylypchuk1991/webix-file-manager-a-worthy-web-counterpart-of-a-desktop-application-62i</link>
      <guid>https://dev.to/serhiipylypchuk1991/webix-file-manager-a-worthy-web-counterpart-of-a-desktop-application-62i</guid>
      <description>&lt;p&gt;The tendencies of recent years show that the age of desktop apps, in their classical sense, is running out. Just as at one time floppies were superseded by CD/DVDs, and the last ones were replaced by flashcards and cloud technologies, so the desktop programs will gradually be replaced by their more modern and practical web counterparts.&lt;/p&gt;

&lt;p&gt;If you develop your own web application that implies working with files, then you will need a good file manager. And here you have to decide between two reasonable options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;either create a widget from scratch, which in any case will require a lot of your time and resources&lt;/li&gt;
&lt;li&gt;or use a ready-made solution and just integrate it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, the proponents of the first option, for whom the development of an effective file system is not a difficult task, may familiarize themselves with an unconventional solution to the issue by other developers.&lt;/p&gt;

&lt;p&gt;The adherents of the second option, for whom the efficiency and result are more precious than the thorny path of achieving it, will open up for themselves a very useful and flexible tool. Further, we will talk about a complex widget for managing files from the Webix team. Let's see what they offer to us.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Webix File Manager
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://webix.com/filemanager/" rel="noopener noreferrer"&gt;&lt;strong&gt;Webix File Manager&lt;/strong&gt;&lt;/a&gt; is a JavaScript file system management solution. The widget is based on the components of the &lt;em&gt;Webix UI&lt;/em&gt; library and the &lt;em&gt;Webix Jet&lt;/em&gt; microframework. Besides the interface for working with file systems, it includes the ready-made Node JS and Golang backend solutions, as well as a service for previewing text files and pictures. For such a significant bonus, we can give the widget a big plus.&lt;/p&gt;

&lt;p&gt;The File Manager functionality is not inferior to the related desktop app. In particular, the widget allows you to do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create new files/folders&lt;/li&gt;
&lt;li&gt;upload local files&lt;/li&gt;
&lt;li&gt;download files&lt;/li&gt;
&lt;li&gt;edit text files using a special editor&lt;/li&gt;
&lt;li&gt;play audio and video files using a built-in player&lt;/li&gt;
&lt;li&gt;move, sort, rename, cut, paste, copy and delete files/folders.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The above-mentioned functionality is implemented through the convenient and stylish interface that displays the structure of files and folders received from the server. Visually the widget consist of 3 parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Toolbar&lt;/li&gt;
&lt;li&gt;Left panel&lt;/li&gt;
&lt;li&gt;Right panel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnh4vhzr14mkp3h8axreb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnh4vhzr14mkp3h8axreb.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;left panel&lt;/em&gt; of the application displays the main directory tree. Here you can look through the tree structure of folders, as well as create or upload new folders and files using the button at the very top of the panel. &lt;/p&gt;

&lt;p&gt;If you select any folder in the directory tree, its content will be displayed on the &lt;em&gt;right panel&lt;/em&gt;. There you can work with files and folders via the context menu, sort and move them, play audio and video files, edit text files, as well as navigate through the directory tree using the navigation bar. Besides, you can establish a convenient display mode.&lt;/p&gt;

&lt;p&gt;It is worth noting here that the widget allows you to display the folder content as a table and cards. But if you're feeling nostalgic for the classic Total Commander interface, you can use the special &lt;em&gt;old-school&lt;/em&gt; mode, which splits the &lt;em&gt;right panel&lt;/em&gt; into two separate parts. This is very comfortable when you need to work with two directories at the same time. There are corresponding buttons on the Toolbar to switch between these display modes.&lt;/p&gt;

&lt;p&gt;Among other things, you can search for the items you need via the search bar and apply a preview mode of a specific file using the related control. Both of them are also on the Toolbar.&lt;/p&gt;

&lt;p&gt;But the most important thing is that you can customize the basic functionality and interface, change it, add your own, or remove those features and components that are not needed. We can give the widget one more point for its flexibility and customization.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Create the Widget with Basic Functionality
&lt;/h2&gt;

&lt;p&gt;Like other &lt;a href="https://webix.com/widget/complex-widgets/" rel="noopener noreferrer"&gt;complex widgets&lt;/a&gt;, File Manager is an advanced extension of the Webix UI library. It is distributed with the Pro version of the library but is not included in it. The component can be purchased as a part of one of the &lt;a href="https://webix.com/filemanager/#licensing" rel="noopener noreferrer"&gt;license packages&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But you can &lt;a href="https://webix.com/filemanager/download.html" rel="noopener noreferrer"&gt;download&lt;/a&gt; the trial Pro version with all complex widgets and use it for free for 30 days. This will allow you to try in practice all the advantages and flexibility of working with the File Manager and decide whether it suits you or not. As for me, that is a rhetorical question.&lt;/p&gt;

&lt;p&gt;Since the File Manager is a library extension, for using it you need first connect the Webix resources. After the library is connected, you have to specify the corresponding &lt;strong&gt;&lt;em&gt;.js&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;.css&lt;/em&gt;&lt;/strong&gt; files of the widget itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- Webix Library --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"codebase/webix.js"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"codebase/webix.css"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- File Manager Widget --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"codebase/filemanager.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"codebase/filemanager.css"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, you should call the widget' constructor wrapped into the &lt;code&gt;webix.ready(…)&lt;/code&gt; method, to start executing the code only after the page is fully loaded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&gt;File&lt;/span&gt; &lt;span class="nx"&gt;Manager&lt;/span&gt; &lt;span class="nx"&gt;Constructor&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
         &lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;filemanager&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;some_backend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
         &lt;span class="p"&gt;});&lt;/span&gt;
       &lt;span class="p"&gt;});&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, to connect the file manager all you need to do is write a few lines of code. Now you can manage the files and folders via the user-friendly interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Configure the Widget
&lt;/h2&gt;

&lt;p&gt;File Manager is a complex widget. It is like a constructor that consists of many separate Webix components. Each of them has its own API, with which you can set its view and behavior. In addition to the nested component settings, the widget includes its own configuration.&lt;/p&gt;

&lt;p&gt;It is worth clarifying here that for configuring the widget plain and convenient JSON syntax is used. All you need to do is to specify the necessary values for the related properties.&lt;/p&gt;

&lt;p&gt;When configuring the app, you need to provide a link to the server script (your own or built-in), to load the data for visualizing the file system. For this, the widget has the &lt;strong&gt;&lt;em&gt;url&lt;/em&gt;&lt;/strong&gt; property. It is worth noting here that the widget won't download all the data at once, but only the main directory and the initially opened folder. The content of other directories will be loaded as needed (upon opening) and cached.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;filemanager&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;your_backend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// your server script&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you do not need to edit text files and play audio/video files, you can just disable the built-in editor and player. For this, you have to use the corresponding &lt;strong&gt;&lt;em&gt;editor&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;player&lt;/em&gt;&lt;/strong&gt; properties.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;filemanager&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;your_backend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// disable built-in editor&lt;/span&gt;
  &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="c1"&gt;// disable built-in player&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, files and folders are displayed as a table. But you can display the current folder content as cards using the &lt;strong&gt;&lt;em&gt;mode&lt;/em&gt;&lt;/strong&gt; property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;filemanager&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;your_backend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// ID for access the widget&lt;/span&gt;
  &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cards&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// default display mode&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Besides the main parameters, the widget has reactive properties. They store the application state and allow changing it dynamically. Here are some of them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;mode&lt;/em&gt;&lt;/strong&gt; (string) - stores the current display mode&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;path&lt;/em&gt;&lt;/strong&gt; (string) - stores the path to the currently open folder.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For working with app state the library provides the &lt;code&gt;getState()&lt;/code&gt; method. With its help, you can get an object with reactive properties and change its values if needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// returns an object with the current state of the File manager&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;getState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can change the default &lt;em&gt;“cards”&lt;/em&gt; mode to the &lt;em&gt;“grid”&lt;/em&gt; mode for displaying the files and folders as a table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// switch the widget to the "grid" mode&lt;/span&gt;
&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;grid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you know how to configure the widget and manage its state. &lt;/p&gt;

&lt;h2&gt;
  
  
  How to Localize the Widget
&lt;/h2&gt;

&lt;p&gt;Localization is a nice bonus provided by the file manager. By default, all widget labels are displayed in English. But you can easily add your own and switch between them if needed.&lt;/p&gt;

&lt;p&gt;To translate labels into the desired language, you can create your own locale and specify the necessary translations inside of its object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fileManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locales&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;custom_ru&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Files&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Add New&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Add new&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;My Files&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;My files&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the custom locale is ready, you can apply it to the entire application. For this, you need to use the &lt;strong&gt;&lt;em&gt;locale&lt;/em&gt;&lt;/strong&gt; property. In the object of this property, you can set your locale value to the &lt;strong&gt;&lt;em&gt;lang&lt;/em&gt;&lt;/strong&gt; property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ui &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;filemanager&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;your_backend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
      &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;custom_ru&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But that's not all. You can also create several locales and switch between them dynamically. To do this, you need to access the built-in &lt;strong&gt;&lt;em&gt;locale&lt;/em&gt;&lt;/strong&gt; service using the &lt;code&gt;getService()&lt;/code&gt; method, and call the &lt;code&gt;setLang()&lt;/code&gt; method for it. The method takes the name of the required locale as a parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;getService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;locale&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setLang&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* desired locale */&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ru, en, ua …&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all the magic. It should be borne in mind that Webix developers don’t provide ready-made files with locales. But the library has a special platform where users can share their locales. These translations can be found on the &lt;a href="https://github.com/webix-hub/locales" rel="noopener noreferrer"&gt;webix-hub&lt;/a&gt; page.&lt;/p&gt;

&lt;p&gt;You can also share your work by pushing it to the related repository on this platform. And we can give the widget one more huge plus for the localization and its simplicity.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Customize File Manager
&lt;/h2&gt;

&lt;p&gt;If you are not quite satisfied with the abilities of the basic setting, you can customize the widget on your own (change some part of the interface or add/remove any functionality). But for this, you need to understand how the app code works.&lt;/p&gt;

&lt;p&gt;The widget structure is built as an SPA application based on the &lt;em&gt;MV*&lt;/em&gt; pattern of the &lt;em&gt;Webix Jet&lt;/em&gt; framework. The app interface (&lt;em&gt;View&lt;/em&gt;) is separated from its business logic (&lt;em&gt;Model&lt;/em&gt;). Each element of the interface is an independent component of the Webix library (&lt;em&gt;button, datatable, toolbar,&lt;/em&gt; and others). Significant parts of the interface (&lt;em&gt;toolbar, left panel,&lt;/em&gt; and others), consisting of the components mentioned above, are stored in the separated classes inherited from the &lt;em&gt;JetView&lt;/em&gt; class. And the logic (model) is also stored separately in classes named &lt;strong&gt;“services”&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;To change the widget interface and functionality, you have to be ready to dig a little in its code. And for this, you should understand at least the main aspects of working with the Webix Jet framework. If you are familiar with JavaScript, you won’t have much difficulty.&lt;/p&gt;

&lt;p&gt;Read the "&lt;a href="https://webix-ui.medium.com/webix-jet-framework-through-the-eyes-of-a-freshman-part-1-composition-and-navigation-60976f86d74a" rel="noopener noreferrer"&gt;&lt;strong&gt;Webix Jet framework through the eyes of a freshman&lt;/strong&gt;&lt;/a&gt;" article to find out the basic principles of working with the framework or refer to the documentation for more detailed information.&lt;/p&gt;

&lt;p&gt;Since you will need to learn a new framework, we can give the widget a small minus for this little complication. But in any case, such knowledge will not be superfluous and only expand the range of your competencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Interface Customization
&lt;/h3&gt;

&lt;p&gt;Now let's get down to practice. As I mentioned above, each element of the interface is an independent component, and each significant part of the interface is a separate class consisting of these components. With this in mind, you can easily set, customize, add new, or even remove that part of the interface (or its component) you don’t need.&lt;/p&gt;

&lt;p&gt;Let's say you want to remove the buttons for switching display modes placed on the Toolbar.&lt;/p&gt;

&lt;p&gt;First, you need to create a new class by inheriting it from the class that stores the toolbar interface. Then, you should hide the buttons using the &lt;code&gt;hide()&lt;/code&gt; method. It should be borne in mind here that the developers don’t recommend removing "unnecessary" components. They can be related to the internal logic of the app and their removal may lead to the error.&lt;/p&gt;

&lt;p&gt;All manipulations with the interface need to be done inside the &lt;code&gt;init()&lt;/code&gt; method. It is inherited from the &lt;em&gt;JetView&lt;/em&gt; class and is responsible for displaying items when initializing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomTopBar&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;fileManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;topbar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="c1"&gt;// default logic&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// removing a component can lead to the errors&lt;/span&gt;
    &lt;span class="c1"&gt;// hiding a component is more safety&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;modes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;hide&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, you need to replace the parent class you inherited from with a new one instead. This can be done using the &lt;strong&gt;&lt;em&gt;override&lt;/em&gt;&lt;/strong&gt; property in the widget constructor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;filemanager&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...,&lt;/span&gt;
    &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cards&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// display mode by default&lt;/span&gt;
    &lt;span class="nx"&gt;override&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="nx"&gt;fileManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;topbar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CustomTopBar&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how you can change the widget interface. In my opinion, there is nothing supernatural here.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Logic Customization
&lt;/h3&gt;

&lt;p&gt;The &lt;em&gt;Webix Jet&lt;/em&gt; services are separate classes, which consist of methods for controlling the widget logic. Unlike the &lt;em&gt;View&lt;/em&gt; classes of the interface, the service methods are available for the entire application. Such a method can be called both by the interface itself and by other services. You can customize any service by changing its methods or adding new ones.&lt;/p&gt;

&lt;p&gt;Let's assume that you have your own server-side logic, where the URL and API for working with data are different from the built-in ones. In this case, you need to make some changes to a special &lt;em&gt;Backend&lt;/em&gt; service.&lt;/p&gt;

&lt;p&gt;By default, the request for uploading files of the selected folder includes the &lt;strong&gt;&lt;em&gt;files&lt;/em&gt;&lt;/strong&gt; segment and looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.webix.com/filemanager-backend/files?Id=%2FNewFolder" rel="noopener noreferrer"&gt;https://docs.webix.com/filemanager-backend/files?Id=%2FNewFolder&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The value of the &lt;strong&gt;id&lt;/strong&gt; parameter in the query string is the &lt;strong&gt;id&lt;/strong&gt; of the folder in which you want to load the data.&lt;/p&gt;

&lt;p&gt;But since you have your own backend, the segment may differ from the built-in one and will look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.webix.com/filemanager-backend/custom_segment?Id=%2FNewFolder" rel="noopener noreferrer"&gt;https://docs.webix.com/filemanager-backend/custom_segment?Id=%2FNewFolder&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;To change this segment, you should slightly modify the &lt;code&gt;files()&lt;/code&gt; method of the &lt;em&gt;Backend&lt;/em&gt; service.&lt;/p&gt;

&lt;p&gt;First, you need to create a new class by inheriting it from the class of the Backend service. Then you should change the &lt;code&gt;files()&lt;/code&gt; method by passing to it the desired segment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomBackendService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;filemanager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;backend&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;files&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_files&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;custom_segment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, as in the case with the interface, you need to replace the parent class you inherited from with a new one. This can be done using the well-known &lt;strong&gt;&lt;em&gt;override&lt;/em&gt;&lt;/strong&gt; property in the widget constructor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;webix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;filemanager&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;your_backend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;override&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="nx"&gt;filemanager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;backend&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CustomBackendService&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Redefining the inner classes in this way, you can change the widget interface and logic on your own. You can find out more information with related samples on the &lt;a href="https://docs.webix.com/filemanager__howto.html" rel="noopener noreferrer"&gt;how-to&lt;/a&gt; page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, I have introduced you to the File Manager widget and its main features. As you can see, it is a very flexible and functional component. You can set and customize it as well as integrate it into any framework or library you prefer. &lt;/p&gt;

&lt;p&gt;It is also worth mentioning here that the widget is distributed along with the more advanced &lt;a href="https://webix.com/widgets/document-manager/" rel="noopener noreferrer"&gt;Document Manager&lt;/a&gt; solution. Both widgets are very similar in design and capabilities, but the latter one has several additional benefits. For example, the document manager allows you to do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;comment on the documents&lt;/li&gt;
&lt;li&gt;mark the documents as favorites&lt;/li&gt;
&lt;li&gt;view the history of recently opened documents&lt;/li&gt;
&lt;li&gt;share the documents with others&lt;/li&gt;
&lt;li&gt;remove the documents to the trash.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you prefer to use more advanced functionality, you can choose the &lt;em&gt;Document Manager&lt;/em&gt; widget. But if this functionality is not required, you may give preference to the simplified &lt;em&gt;File Manager&lt;/em&gt; widget. In any case, the final word is yours.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>html</category>
    </item>
    <item>
      <title>How to Create Forms with Webix JavaScript</title>
      <dc:creator>Serhii Pylypchuk</dc:creator>
      <pubDate>Thu, 12 Aug 2021 08:57:50 +0000</pubDate>
      <link>https://dev.to/serhiipylypchuk1991/how-to-create-forms-with-webix-javascript-m61</link>
      <guid>https://dev.to/serhiipylypchuk1991/how-to-create-forms-with-webix-javascript-m61</guid>
      <description>&lt;p&gt;The daily routine of a typical programmer consists of monotonous keystrokes and coffee breaks. A good programmer can reach the desired result with fewer keystrokes. And I don't mean the "&lt;em&gt;Ctrl+C / Ctrl+V&lt;/em&gt;" combination, as you might think :) In this article, I want to tell you how to save precious time and nerves if you need to create a beautiful and functional form.&lt;/p&gt;

&lt;p&gt;There are many libraries that provide a large number of features for working with forms. But today we will consider only one of the most convenient and multifunctional tools for building app interfaces of any complexity. It is about the Webix library and its capabilities.&lt;/p&gt;

&lt;p&gt;To prove that these are not empty words, we will create a small app for bookselling and see how to implement an &lt;strong&gt;order form&lt;/strong&gt; using Webix components.&lt;/p&gt;

&lt;p&gt;You can find the full source code and live demo &lt;a href="https://github.com/serhiipylypchuk1991/book-store-service" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;h1&gt;Webix and Its Capabilities&lt;/h1&gt;

&lt;p&gt;Webix UI is a &lt;a href="https://webix.com/" rel="noopener noreferrer"&gt;JavaScript library&lt;/a&gt; that allows you to create a responsive design without worrying about the app's performance. The range of possibilities is represented by UI components of varying complexity. It can be a simple button and a complex solution. Each widget includes a whole set of methods and properties for flexible configuring and controlling. Besides, the library has extra tools. For example, event handling, methods of working with data, interaction with the server, styling themes and much more. You can find out more information about capabilities in the &lt;a href="https://docs.webix.com/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;. Now it is time to move on to the practice.&lt;/p&gt;

&lt;h1&gt;Main Preparations&lt;/h1&gt;

&lt;p&gt;In order to use the Webix library, we need to include it in the main index.html file. It is worth mentioning here that the library is distributed in 2 versions: the basic &lt;a href="https://webix.com/get-webix-gpl/" rel="noopener noreferrer"&gt;GPL&lt;/a&gt; and extended &lt;a href="https://webix.com/download/" rel="noopener noreferrer"&gt;Pro&lt;/a&gt; version. The GPL version is free and provides a wide set of features that cover 97.26% of our day-to-day needs. But for working with forms, which are the main topic of this article, we will need some special features of the advanced version. I will mention them in the process. Based on this, we will use the extended Pro trial version to get the most impact.&lt;/p&gt;

&lt;p&gt;To get the trial version of the library, we need to visit the &lt;a href="https://webix.com/download/" rel="noopener noreferrer"&gt;download page&lt;/a&gt;, enter the necessary data and get a link for downloading the coveted archive.&lt;/p&gt;

&lt;p&gt;The archive includes the &lt;strong&gt;&lt;em&gt;webix/codebase/&lt;/em&gt;&lt;/strong&gt; folder with two sacred files, namely: &lt;em&gt;webix.js&lt;/em&gt; and &lt;em&gt;webix.css&lt;/em&gt;. In order for the Webix magic to start working, we need to move this folder into the root of our project and include the library source files in the &lt;em&gt;index.html&lt;/em&gt; file:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;It's worth noting that these files are also available via the CDN at the following links:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We'll use local files, as they work faster and do not need Internet access (sometimes it happens). The &lt;em&gt;index.html&lt;/em&gt; file looks like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We have created a basic &lt;em&gt;index.html&lt;/em&gt; file and included all the necessary tools. Let's start with making an overview of our app.&lt;/p&gt;

&lt;h1&gt;Application Overview&lt;/h1&gt;

&lt;p&gt;We have a small bookselling app. It consists of a toolbar and two replaceable modules, namely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;module with a catalog of books&lt;/li&gt;
&lt;li&gt;module with a book description and order form.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The module with the catalog consists of small blocks, 2 items in one row. Each block contains a short description of the product and button to order. It is worth clarifying here that we use the &lt;strong&gt;&lt;a href="https://docs.webix.com/desktop__dataview.html" rel="noopener noreferrer"&gt;dataview&lt;/a&gt;&lt;/strong&gt; widget for creating this module. In the browser, we will see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxu2qk4w6hikm0tuxlviv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxu2qk4w6hikm0tuxlviv.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When clicking on the "&lt;strong&gt;Buy now&lt;/strong&gt;" button, the user will see the module with a detailed description of the product. For its creation we use the &lt;strong&gt;&lt;a href="https://docs.webix.com/desktop__template.html" rel="noopener noreferrer"&gt;template&lt;/a&gt;&lt;/strong&gt; widget. Next to the product description we will place the module with our form, which this article is devoted to. In the browser, we will see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6i1r65310u3ubtb3h746.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6i1r65310u3ubtb3h746.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now our task is to add a module with a form, where the user can enter all the necessary data for ordering. As you may know, the purpose of any form is collecting information from users. In our case, we are going to collect the following data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;information about the order and its delivery&lt;/li&gt;
&lt;li&gt;information about the user&lt;/li&gt;
&lt;li&gt;information about the payment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each form should contain input fields and various controls, namely: checkboxes, radiobuttons, selectors, buttons and much more. Considering the data we need to collect, our form will be large enough.&lt;/p&gt;

&lt;p&gt;If we don't want to scare off the user with a large number of fields and controls, let's divide the form into semantic groups mentioned above. Each group will deal with each particular order step. Group will be placed in a separate tab and the user will be able to navigate back and forth through them. There will be 3 tabs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the first one includes an order form with the possibility to choose between the &lt;em&gt;pick-up&lt;/em&gt; and &lt;em&gt;delivery&lt;/em&gt; options. If the user chooses &lt;em&gt;delivery&lt;/em&gt;, the app will display some extra fields for entering the desired delivery address&lt;/li&gt;
&lt;li&gt;the second one includes a form for user's personal data&lt;/li&gt;
&lt;li&gt;the last tab includes a form to collect information about the user's credit card. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interface of each form will be created in a separate file and saved to a variable. These variables will be used for building the layout in the &lt;em&gt;index.html&lt;/em&gt; file.&lt;/p&gt;

&lt;h1&gt;Layout for Module with Forms&lt;/h1&gt;

&lt;p&gt;In this article, we will not dive into the details of building the entire app layout. If you would like to study this topic more deeply, read the &lt;a href="https://webix-ui.medium.com/creating-a-booking-application-with-webix-ui-32e1ee42e799" rel="noopener noreferrer"&gt;Creating a Booking App with Webix UI&lt;/a&gt; article. You can also refer to the &lt;strong&gt;&lt;a href="https://docs.webix.com/desktop__layout.html" rel="noopener noreferrer"&gt;layout&lt;/a&gt;&lt;/strong&gt; documentation. There you will find an exhaustive description of all properties and methods with corresponding samples.&lt;/p&gt;

&lt;p&gt;Here we are interested in only the part of the layout containing the tabs with forms. These tabs will be switched by the user dynamically. For such cases, Webix provides a special &lt;strong&gt;&lt;a href="https://docs.webix.com/api__refs__ui.multiview.html" rel="noopener noreferrer"&gt;multiview&lt;/a&gt;&lt;/strong&gt; component. The needed modules (in our case it is the forms) have to be placed in the array of the &lt;strong&gt;&lt;em&gt;cells&lt;/em&gt;&lt;/strong&gt; property. When initial loading, the first element of this array will be displayed. To navigate between modules, we need to set them a unique &lt;strong&gt;ID&lt;/strong&gt;. The code of layout looks like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We have created the layout with forms. Now let's get down to the forms directly. And we start with the order form.&lt;/p&gt;

&lt;h1&gt;Order Form&lt;/h1&gt;

&lt;p&gt;The order form will consist of two logical parts. The first part will contain the fields for information about the order itself, and the second one - about its delivery.&lt;/p&gt;

&lt;p&gt;Initially, the form will be displayed only with the "&lt;strong&gt;Order Information&lt;/strong&gt;" section:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9eqbn0qwd4nryx87mh2j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9eqbn0qwd4nryx87mh2j.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second one "&lt;strong&gt;Delivery Information&lt;/strong&gt;" section will be hidden by default. We will show it only if the user selects the corresponding option of the &lt;strong&gt;radio&lt;/strong&gt; control. The order form with 2 sections will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpzhe3s1mvd7f7k2rh7hw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpzhe3s1mvd7f7k2rh7hw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To navigate through the tabs with forms, we will use the "&lt;strong&gt;Back&lt;/strong&gt;" and "&lt;strong&gt;Next&lt;/strong&gt;" buttons. The former button returns us to the catalog of goods, and the latter displays the next form.&lt;/p&gt;

&lt;p&gt;Now let's take a look at how to implement all of this in code.&lt;/p&gt;

&lt;p&gt;To collect data from users, Webix provides a special &lt;a href="https://docs.webix.com/desktop__form.html" rel="noopener noreferrer"&gt;&lt;strong&gt;form&lt;/strong&gt;&lt;/a&gt; widget and a number of related &lt;a href="https://docs.webix.com/desktop__controls.html" rel="noopener noreferrer"&gt;&lt;strong&gt;controls&lt;/strong&gt;&lt;/a&gt;. The form organisation is similar to the &lt;a href="https://docs.webix.com/desktop__layout.html" rel="noopener noreferrer"&gt;&lt;strong&gt;layout&lt;/strong&gt;&lt;/a&gt; component. We can divide form into rows and columns, putting the necessary controls into the corresponding containers.&lt;/p&gt;

&lt;p&gt;We create a form in the &lt;em&gt;order_form.js&lt;/em&gt; file and save it to the &lt;strong&gt;order_form&lt;/strong&gt; variable:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here we also need to define the form layout mentioned above. For doing this, the widget has dedicated &lt;a href="https://docs.webix.com/api__link__ui.form_cols_config.html" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;cols&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://docs.webix.com/api__link__ui.form_rows_config.html" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;rows&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://docs.webix.com/api__link__ui.form_elements_config.html" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;elements&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; properties. The first two properties allow us to divide the component interface into columns and rows. The &lt;strong&gt;&lt;em&gt;elements&lt;/em&gt;&lt;/strong&gt; property we are going to use, allows us to place the form elements as rows. All we need to do is to place two sections with the desired fields into the array of this property. Now let's tackle these sections.&lt;/p&gt;

&lt;h2&gt;The "Order Information" Section&lt;/h2&gt;

&lt;p&gt;To group the form fields into sections, we use the &lt;a href="https://docs.webix.com/api__refs__ui.fieldset.html" rel="noopener noreferrer"&gt;&lt;strong&gt;fieldset&lt;/strong&gt;&lt;/a&gt; component. The first section is "&lt;strong&gt;Order Information&lt;/strong&gt;". It combines several inputs for collecting the order data. The name of this section is defined via the &lt;strong&gt;&lt;em&gt;label&lt;/em&gt;&lt;/strong&gt; property. The desired controls will be described in the object of the &lt;strong&gt;&lt;em&gt;body&lt;/em&gt;&lt;/strong&gt; property.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;All the fields within this section will be arranged in rows. For this, we need to put them inside the array of the &lt;strong&gt;&lt;em&gt;rows&lt;/em&gt;&lt;/strong&gt; property. Now let's create these fields.&lt;/p&gt;

&lt;h3&gt;Special Field for Order Name&lt;/h3&gt;

&lt;p&gt;Let's start with the field that contains the order name. It doesn't need any data entry, since its value is set dynamically. To create this field, we can use 2 label components and arrange them as columns. The first component will contain the field name, and the second one will contain the name of the selected item (in our case it is the book title).&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now the section looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3817e11u5mm86i4377jd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3817e11u5mm86i4377jd.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the second label we need to set the &lt;strong&gt;&lt;em&gt;name&lt;/em&gt;&lt;/strong&gt; property to the &lt;strong&gt;&lt;em&gt;order_name&lt;/em&gt;&lt;/strong&gt; value. The unique name is required to access corresponding form elements. The reason is that the value of this control will be set and read dynamically via the form API. We also need to specify the unique names for other fields, the values ​​of which we are going to set or read.&lt;/p&gt;

&lt;h3&gt;Control for Goods Amount Setting&lt;/h3&gt;

&lt;p&gt;In this section we need to give the user an ability to indicate the desired number of goods. To do this, let's use the special &lt;a href="https://docs.webix.com/desktop__counter.html" rel="noopener noreferrer"&gt;&lt;strong&gt;counter&lt;/strong&gt;&lt;/a&gt; tool and specify its label and unique name. We can also define the min and max values via the dedicated &lt;strong&gt;&lt;em&gt;min&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;max&lt;/em&gt;&lt;/strong&gt; properties.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now the section looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3s5phx5y3trmhms0lh93.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3s5phx5y3trmhms0lh93.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Input Field for Gift Card&lt;/h3&gt;

&lt;p&gt;Now let's create a field where the user can enter a gift card number. It is best to use the &lt;a href="https://docs.webix.com/desktop__text.html" rel="noopener noreferrer"&gt;&lt;strong&gt;text&lt;/strong&gt;&lt;/a&gt; control here. Besides the name and label, we can set a placeholder via the &lt;strong&gt;&lt;em&gt;placeholder&lt;/em&gt;&lt;/strong&gt; property and a special icon on the right part of the field via the &lt;strong&gt;&lt;em&gt;clear&lt;/em&gt;&lt;/strong&gt; property. The icon will appear when the user enters data in the field. When he clicks on this icon, the entered data will be deleted and the icon will disappear.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now the section looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkhit0sf4bq5du8yj7j28.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkhit0sf4bq5du8yj7j28.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Special Field for Order Price&lt;/h3&gt;

&lt;p&gt;Next, we have a field for displaying the order price. The price, as well as the order name, is set dynamically via the form's API and changes depending on the selected parameters. Here we do the same as with the order name field: use 2 &lt;a href="https://docs.webix.com/desktop__label.html" rel="noopener noreferrer"&gt;&lt;strong&gt;label&lt;/strong&gt;&lt;/a&gt; components, place them as columns and set the name to the second one through its &lt;strong&gt;&lt;em&gt;name&lt;/em&gt;&lt;/strong&gt; property.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now the section looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2kwtzqgdhde58dxtdr9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2kwtzqgdhde58dxtdr9.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Control for Order Receiving Method&lt;/h3&gt;

&lt;p&gt;In this section, we have to implement the field where the user can select the receiving order method: pick-up or delivery. We can do this via the &lt;a href="https://docs.webix.com/desktop__radio.html" rel="noopener noreferrer"&gt;&lt;strong&gt;radio&lt;/strong&gt;&lt;/a&gt; control with two options. The label of this control will be empty, because the radio button names are informative enough. The options data for the radio buttons are set via the &lt;strong&gt;&lt;em&gt;options&lt;/em&gt;&lt;/strong&gt; property.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now let's make it so that if the user switches between the "&lt;em&gt;Delivery&lt;/em&gt;" and "&lt;em&gt;Pick-up&lt;/em&gt;" options, the "&lt;strong&gt;Delivery Information&lt;/strong&gt;" section will be displayed or hidden correspondingly. Let me remind you that the "&lt;em&gt;Pick-up&lt;/em&gt;" option is selected by default, and the section itself is hidden.&lt;/p&gt;

&lt;p&gt;To handle the desired event, we need to specify the special &lt;strong&gt;&lt;em&gt;on&lt;/em&gt;&lt;/strong&gt; property into the constructor of the &lt;strong&gt;radio&lt;/strong&gt; control. In the object of this property, we also need to specify the required event (in our case, it is &lt;em&gt;onChange&lt;/em&gt;) and set to it the desired handler.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;First, we get the current value of the &lt;strong&gt;radio&lt;/strong&gt; control via its &lt;code&gt;getValue()&lt;/code&gt; method. If the value is 1 (the "&lt;em&gt;pick-up&lt;/em&gt;" option is selected), we will hide the "&lt;strong&gt;Delivery Information&lt;/strong&gt;" section via its &lt;code&gt;hide()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;If the value is 2 (the "&lt;em&gt;delivery&lt;/em&gt;" option is selected), we will display the "&lt;strong&gt;Delivery Information&lt;/strong&gt;" section via its &lt;code&gt;show()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;The whole section looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyktlnysgpne0oos8yauh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyktlnysgpne0oos8yauh.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;The "Delivery Information" Section&lt;/h2&gt;

&lt;p&gt;Now let's move on to the "&lt;strong&gt;Delivery Information&lt;/strong&gt;" section. It combines the fields for entering the delivery address. We create it in the same way as the previous "&lt;strong&gt;Order Information&lt;/strong&gt;" section. As mentioned above, this section is hidden by default. To do this, we need to set its &lt;strong&gt;&lt;em&gt;hidden&lt;/em&gt;&lt;/strong&gt; property to &lt;em&gt;true&lt;/em&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;To ship the order, we need to get a delivery address. For this, we will create special fields in which the user can enter the following parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;country&lt;/li&gt;
&lt;li&gt;address within the country:

&lt;ul&gt;
&lt;li&gt;region&lt;/li&gt;
&lt;li&gt;city&lt;/li&gt;
&lt;li&gt;street and house&lt;/li&gt;
&lt;li&gt;zip code&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;desired shipping date&lt;/li&gt;

&lt;li&gt;additional instructions.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Besides, we will provide the user with the ability to insure the delivery. And as a nice bonus, the user will be able to choose the desired packaging color, which I personally attach great importance to :) Now let's start implementing our plan.&lt;/p&gt;

&lt;h3&gt;Control for Country Selection&lt;/h3&gt;

&lt;p&gt;Let's make it so that the user doesn’t enter the country name but selects it from the drop-down list. For creating this field we can use the &lt;a href="https://docs.webix.com/desktop__combo.html" rel="noopener noreferrer"&gt;&lt;strong&gt;combo&lt;/strong&gt;&lt;/a&gt; tool of the Webix library. In addition to the standard set of properties ( &lt;em&gt;label, name, clear and placeholder&lt;/em&gt; ), we need to parse data for the drop-down list options. This is done via the &lt;strong&gt;&lt;em&gt;options&lt;/em&gt;&lt;/strong&gt; property. The data can be set either as an array with data (if they are on the client) or as the path to the data on the server. The data schema should be as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Canada"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"United Kingdom"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The library allows us to make the fields required for filling. To do this, we need to set the &lt;strong&gt;&lt;em&gt;required&lt;/em&gt;&lt;/strong&gt; property to &lt;em&gt;true&lt;/em&gt;. As a result, we will see a special red marker at the top right corner of the label. Looking ahead, if the user leaves such a field empty and runs validation, it will turn in red and the data will not be sent.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Now the section looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2jdba24k0chtqdzxyp5c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2jdba24k0chtqdzxyp5c.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Input Fields for Delivery Address&lt;/h3&gt;

&lt;p&gt;All the fields for addresses within the country will contain the same settings. To create them, we use the well-known &lt;strong&gt;text&lt;/strong&gt; control and a set of basic properties: &lt;em&gt;label, name, clear, placeholder and required&lt;/em&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now the section looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gsuuj9o2tj89xez1agr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gsuuj9o2tj89xez1agr.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Control for Shipping Date Selection&lt;/h3&gt;

&lt;p&gt;We can ask the user about the desired shipping date of the order. And here, instead of the usual input field, Webix provides us with a special &lt;a href="https://docs.webix.com/desktop__datepicker.html" rel="noopener noreferrer"&gt;&lt;strong&gt;datepicker&lt;/strong&gt;&lt;/a&gt; widget. When the user clicks on it, the component will display a compact calendar, in which he can select the required shipping date. In addition to the basic properties mentioned above, we can specify the format for displaying the date via the &lt;strong&gt;&lt;em&gt;format&lt;/em&gt;&lt;/strong&gt; property. To read more about all capabilities of this widget, visit its &lt;a href="https://docs.webix.com/api__refs__ui.datepicker.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; page.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now the section looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flpoz4t5p3a06deppyfsx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flpoz4t5p3a06deppyfsx.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Field for Additional Instructions&lt;/h3&gt;

&lt;p&gt;It is difficult to foresee the fields for each specific situation. Sometimes it happens that the user wants to specify the additional delivery instructions. For example, he wants the order to be left on the porch of the house or packed in additional packaging. Let's give the user such ability in our form.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.webix.com/desktop__textarea.html" rel="noopener noreferrer"&gt;&lt;strong&gt;textarea&lt;/strong&gt;&lt;/a&gt; component is the best decision for such an issue. If you have worked with plain HTML forms, you should be familiar with this element. In addition to the standard settings of this widget, we will set a fixed height via its &lt;strong&gt;&lt;em&gt;height&lt;/em&gt;&lt;/strong&gt; property.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now the section looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz4z9b8h0ndzwjgrj3vtf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz4z9b8h0ndzwjgrj3vtf.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Control for Applying Insurance&lt;/h3&gt;

&lt;p&gt;Let's provide our users with the ability to insure order delivery.&lt;/p&gt;

&lt;p&gt;To apply for insurance, we will use the &lt;a href="https://docs.webix.com/desktop__switch.html" rel="noopener noreferrer"&gt;&lt;strong&gt;switch&lt;/strong&gt;&lt;/a&gt; control. It is a toggle button that allows the user to switch between two opposite values ​​(0 and 1). Besides the label and name, we can specify 2 inside labels for active and passive states. This can be done via its &lt;strong&gt;&lt;em&gt;onLabel&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;offLabel&lt;/em&gt;&lt;/strong&gt; properties.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;Control for Сolor Selection&lt;/h3&gt;

&lt;p&gt;As mentioned above, we will give users the ability to choose the packaging color. For this, the Webix library provides several widgets, namely: &lt;a href="https://docs.webix.com/desktop__colorpicker.html" rel="noopener noreferrer"&gt;&lt;strong&gt;colorpicker&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://docs.webix.com/desktop__colorselector.html" rel="noopener noreferrer"&gt;&lt;strong&gt;colorselect&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://docs.webix.com/desktop__colorboard.html" rel="noopener noreferrer"&gt;&lt;strong&gt;colorboard&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since we only have 4 types of color packages, the best option would be the &lt;strong&gt;colorboard&lt;/strong&gt; widget with a limited palette.&lt;/p&gt;

&lt;p&gt;We can specify the palette colors via the &lt;strong&gt;&lt;em&gt;palette&lt;/em&gt;&lt;/strong&gt; property and the default color via the &lt;strong&gt;&lt;em&gt;value&lt;/em&gt;&lt;/strong&gt; property. Let's also set fixed dimensions for each palette box via the corresponding &lt;strong&gt;&lt;em&gt;width&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;height&lt;/em&gt;&lt;/strong&gt; properties, and remove the border around the component using its &lt;strong&gt;&lt;em&gt;borderless&lt;/em&gt;&lt;/strong&gt; property.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The whole section looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgq5vf6jzsmar9vhv7fpz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgq5vf6jzsmar9vhv7fpz.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Buttons for Navigation&lt;/h2&gt;

&lt;p&gt;For the order form we have to implement one more important part. It is about buttons for switching to the next form and back to the trade list. For creating these buttons we will use the &lt;a href="https://docs.webix.com/desktop__button.html" rel="noopener noreferrer"&gt;&lt;strong&gt;button&lt;/strong&gt;&lt;/a&gt; component.&lt;/p&gt;

&lt;p&gt;To apply built-in styling, we need to set the css property to the corresponding webix class. In our case, it is about the &lt;em&gt;webix_secondary&lt;/em&gt; and &lt;em&gt;webix_primary&lt;/em&gt; classes.&lt;/p&gt;

&lt;p&gt;The button name is set via its &lt;strong&gt;&lt;em&gt;label&lt;/em&gt;&lt;/strong&gt; property. For completeness, it is worth noting that along with the label of each button, we will place a small arrow to indicate the button's purpose. The left arrow for going back (in this case, to the goods list), and the right one for going forward to the next form. To define built-in webix icons, we need to use dedicated css classes.&lt;/p&gt;

&lt;p&gt;Both these buttons will be displayed as columns. For this, we need to put them into the array of the &lt;strong&gt;&lt;em&gt;cols&lt;/em&gt;&lt;/strong&gt; property.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The buttons look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffdli8kquu97ffqk3takf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffdli8kquu97ffqk3takf.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The order form interface is ready. Now we need to include the &lt;em&gt;order_form.js&lt;/em&gt; file into &lt;em&gt;index.html&lt;/em&gt; and put the &lt;strong&gt;order_form&lt;/strong&gt; variable into the layout code. In the browser, we will see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffx67ackf8tl2cpo8593r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffx67ackf8tl2cpo8593r.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;User Form&lt;/h2&gt;

&lt;p&gt;After the user has entered the necessary information about the order, we need to get his personal data. It is required for identifying the user when he comes to pick up his order or receives it through the delivery service.&lt;/p&gt;

&lt;p&gt;Let's create a separate form with fields for entering the following personal data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;first and last name&lt;/li&gt;
&lt;li&gt;age&lt;/li&gt;
&lt;li&gt;gender&lt;/li&gt;
&lt;li&gt;contact information:

&lt;ul&gt;
&lt;li&gt;email&lt;/li&gt;
&lt;li&gt;phone number.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The user form will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffx67ackf8tl2cpo8593r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffx67ackf8tl2cpo8593r.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's see how to implement this in the code.&lt;/p&gt;

&lt;p&gt;We create a form in the &lt;em&gt;user_form.js&lt;/em&gt; file and save it to the &lt;strong&gt;user_form&lt;/strong&gt; variable. After this we define the "&lt;strong&gt;User Information&lt;/strong&gt;" section with the fields mentioned above.&lt;/p&gt;

&lt;h3&gt;Input Fields for First and Last Name&lt;/h3&gt;

&lt;p&gt;Now let's move on to the fields in which the user can enter its first and last name. To create them, we can use the well-known &lt;strong&gt;text&lt;/strong&gt; control. As in the previous form, for these controls we also specify a standard set of properties, namely: &lt;em&gt;label, name, placeholder, clear and required&lt;/em&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now the section looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8mdqq4q7vjrsmhkixni.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8mdqq4q7vjrsmhkixni.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Controls for Age and Gender&lt;/h3&gt;

&lt;p&gt;Next, we have 2 optional fields. It is about a counter with which the user can indicate his age and radio buttons for choosing a gender.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Counter&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To get the user age, we can use the &lt;strong&gt;counter&lt;/strong&gt; control. We have already used it to define the number of goods.&lt;/p&gt;

&lt;p&gt;The age of our customer should be in the range from 18 to 100. These parameters can be set via the &lt;strong&gt;&lt;em&gt;min&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;max&lt;/em&gt;&lt;/strong&gt; properties.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Radio&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To get the user gender, we can use the &lt;strong&gt;radio&lt;/strong&gt; control. We have also used it to select the method of the order receiving. The widget will consist of 2 options, namely: &lt;em&gt;Male&lt;/em&gt; and &lt;em&gt;Female&lt;/em&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now the section looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faoc02kvbdx4b78sziub8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faoc02kvbdx4b78sziub8.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Input Fields for Contact Information&lt;/h3&gt;

&lt;p&gt;To contact the user for clarifying any additional information and notifying about the order readiness or its dispatch, we need to get its contact information.&lt;/p&gt;

&lt;p&gt;Let's create 2 fields in which the user can enter his email and phone number. For this, we use the &lt;strong&gt;text&lt;/strong&gt; control and specify the set of standard properties (&lt;em&gt;label, name, placeholder, clear and required&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;A special emphasis should be placed on the phone number field. Here we can apply a special mask for entering a phone number. To do this we need to set the &lt;strong&gt;&lt;em&gt;pattern&lt;/em&gt;&lt;/strong&gt; property to the built-in &lt;code&gt;webix.patterns.phone&lt;/code&gt; value. It is worth mentioning here that this is one of those features that are available only in the PRO version. In &lt;a href="https://docs.webix.com/desktop__formatted_text_inputs.html" rel="noopener noreferrer"&gt;this&lt;/a&gt; article, you can find more information about the input field formatting.&lt;/p&gt;

&lt;p&gt;The mask allows users to enter only 11 characters of the phone number, adds a "+" sign at the beginning of the number and encloses the telephone operator code in parentheses. Other characters will be ignored.&lt;/p&gt;

&lt;p&gt;Let's give a little hint for filling this field and add a short message at the bottom of the input. For this, we can use the &lt;strong&gt;&lt;em&gt;bottomLabel&lt;/em&gt;&lt;/strong&gt; property.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The whole section looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5nd27n3xtagesnwlr81.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5nd27n3xtagesnwlr81.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this form, we also need to add navigation buttons. Here we don't have to bother too much and just copy the similar code from the previous form. The differences will only be visible when we make these buttons workable.&lt;/p&gt;

&lt;p&gt;The user form interface is ready. Now we just need to include the &lt;em&gt;user_form.js&lt;/em&gt; file into &lt;em&gt;index.html&lt;/em&gt; and put the &lt;strong&gt;user_form&lt;/strong&gt; variable into layout code. In the browser, we will see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3r4grx1wpceubhqohloc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3r4grx1wpceubhqohloc.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;Payment form&lt;/h1&gt;

&lt;p&gt;After the user has entered personal data, we need to get his credit card information for paying the order through a special service.&lt;/p&gt;

&lt;p&gt;Let's create a separate form for payment information and collect the following data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;card number&lt;/li&gt;
&lt;li&gt;cardholder's name&lt;/li&gt;
&lt;li&gt;expiration date&lt;/li&gt;
&lt;li&gt;CVV code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The payment form will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz8vn1go5qxq3l8igiwww.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz8vn1go5qxq3l8igiwww.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We create a form in the &lt;em&gt;payment_form.js&lt;/em&gt; file and save it to the &lt;strong&gt;payment_form&lt;/strong&gt; variable. After this, we define the "&lt;strong&gt;Payment Information&lt;/strong&gt;" section with the fields mentioned above.&lt;/p&gt;

&lt;p&gt;The first field is intended for the card number. Besides the standard properties of the &lt;strong&gt;text&lt;/strong&gt; control (&lt;em&gt;label, name, placeholder, clear and required&lt;/em&gt;), we also specify a built-in mask for entering the card number: &lt;code&gt;pattern: webix.patterns.card&lt;/code&gt;. It means that the user can enter only 16 digits indicated on the front of his card. Other characters will be ignored. I would like to remind you that masks are only available in the Pro version.&lt;/p&gt;

&lt;p&gt;Next, we need to create a field for entering the name of the cardholder. The &lt;strong&gt;text&lt;/strong&gt; control of this field will also include the standard set of properties mentioned above.&lt;/p&gt;

&lt;p&gt;The controls for selecting card expiration date deserve more attention. Here we can use 2 &lt;a href="https://docs.webix.com/desktop__richselect.html" rel="noopener noreferrer"&gt;&lt;strong&gt;richselect&lt;/strong&gt;&lt;/a&gt; components. When the user clicks on it, the widget will display a drop-down list with options. The data for these options are set via the &lt;strong&gt;&lt;em&gt;options&lt;/em&gt;&lt;/strong&gt; property.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now we move on to the field for entering the CVV code. Here the user needs to enter 3 secret digits indicated on the back of the card. The &lt;strong&gt;text&lt;/strong&gt; control of this field will also include a standard set of properties. Besides, we can set the &lt;strong&gt;&lt;em&gt;type&lt;/em&gt;&lt;/strong&gt; property to the &lt;code&gt;password&lt;/code&gt; value, to define the type of the field. It will display asterisks instead of the entered data. We will also specify a custom mask via the &lt;strong&gt;&lt;em&gt;pattern&lt;/em&gt;&lt;/strong&gt; property. So now the user can enter only 3 digits of the CVV code.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let's add some control for saving the entered data in the browser settings. If the user enters data and checks this control, he can reuse payment data the next time. For this, we use the &lt;a href="https://docs.webix.com/desktop__checkbox.html" rel="noopener noreferrer"&gt;&lt;strong&gt;checkbox&lt;/strong&gt;&lt;/a&gt; control with the &lt;strong&gt;&lt;em&gt;name&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;labelRight&lt;/em&gt;&lt;/strong&gt; properties. The second property will display the label on the right part of the control&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;For this form, we also need to add corresponding buttons for going back and making the order. Here we just copy the similar code from the previous form and rename the second button to "&lt;strong&gt;Make order&lt;/strong&gt;".&lt;/p&gt;

&lt;p&gt;The payment form interface is ready. Now we just need to include the &lt;em&gt;payment_form.js&lt;/em&gt; file into index.html and put the &lt;strong&gt;payment_form&lt;/strong&gt; variable into layout code. In the browser, we will see the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiw7i62kp45gwd3kufw8r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiw7i62kp45gwd3kufw8r.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;How to Get the App Working&lt;/h1&gt;

&lt;p&gt;Above we have described the layout and interface of our forms. But this is only half the way. Now let's get them to work. And for this, Webix has all the necessary tools.&lt;/p&gt;

&lt;h3&gt;The List of Goods&lt;/h3&gt;

&lt;p&gt;And we will start from the main page, where the list of goods is displayed. Each block on this page consists of a short description and the "&lt;strong&gt;Buy now&lt;/strong&gt;" button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figyyjs2wzyd3hnrn3d1d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figyyjs2wzyd3hnrn3d1d.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the user clicks on this button, we need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;show the module with the order form&lt;/li&gt;
&lt;li&gt;fill out the order form with the data of the selected book.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To implement the mentioned above, we need to handle the button &lt;strong&gt;click&lt;/strong&gt; event. This can be done via the corresponding &lt;strong&gt;&lt;em&gt;onClick&lt;/em&gt;&lt;/strong&gt; property of the &lt;strong&gt;dataview&lt;/strong&gt; widget. Inside the object of this property, we specify the &lt;em&gt;css&lt;/em&gt; class of our button and set a handler to it as a value.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;To fill out the order form fields, we can use its &lt;code&gt;setValues()&lt;/code&gt; method and pass the object with the needed data as a parameter.&lt;/p&gt;

&lt;p&gt;As you remember, we have set the name for all form fields via the &lt;strong&gt;&lt;em&gt;name&lt;/em&gt;&lt;/strong&gt; property. In the data object, we use these names as the keys and set them to the corresponding values.&lt;/p&gt;

&lt;p&gt;If we pass only the data object to the method, it will remove all the form values ​​and set new values specified in the object. In this case, the delivery information will also be cleared and the user will need to enter the address again.&lt;/p&gt;

&lt;p&gt;To avoid this inconvenience, we can pass the &lt;code&gt;true&lt;/code&gt; value to the method as the second parameter. So now the method will change only the values passed in the object.&lt;/p&gt;

&lt;p&gt;After all the data manipulation, we can switch the &lt;strong&gt;multiview&lt;/strong&gt; component to the next module using its &lt;code&gt;show()&lt;/code&gt; method.&lt;/p&gt;

&lt;h3&gt;How to Calculate the Order Price&lt;/h3&gt;

&lt;p&gt;Now we need to calculate the order price and update it every time when the user changes the number of goods or applies the insurance control.&lt;/p&gt;

&lt;p&gt;To listen to any change in the form fields, we need to use the &lt;strong&gt;&lt;em&gt;on&lt;/em&gt;&lt;/strong&gt; property. In the object of this property, we can specify the desired event and its handler.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;So now we need to create this handler. And it will look like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here we get an object with the form values ​​via its &lt;code&gt;getValues()&lt;/code&gt; method. It is worth noting that this object will include only the fields value with the &lt;strong&gt;&lt;em&gt;name&lt;/em&gt;&lt;/strong&gt; property.&lt;/p&gt;

&lt;p&gt;The price variable stores the total goods price. It depends on the initial price (set in the hidden &lt;em&gt;initial_price&lt;/em&gt; field) and the goods count.&lt;/p&gt;

&lt;p&gt;Next, we need to check the insurance that can be applied in the "&lt;strong&gt;Delivery Information&lt;/strong&gt;" section and will affect the order price. For this, we check the visibility of the "&lt;strong&gt;Delivery Information&lt;/strong&gt;" section using the &lt;code&gt;isVisible()&lt;/code&gt; method. It returns &lt;em&gt;true&lt;/em&gt; if the section is visible and &lt;em&gt;false&lt;/em&gt; if not.&lt;/p&gt;

&lt;p&gt;If the section is visible, we need to check the state of the &lt;strong&gt;switch&lt;/strong&gt; control (if enabled - value &lt;code&gt;1&lt;/code&gt;, if disabled - value &lt;code&gt;0&lt;/code&gt;) and generate the final order cost. If the insurance is applied, we will increase the cost by 20%.&lt;/p&gt;

&lt;p&gt;When the final order price is ready, we need to update it in the corresponding &lt;strong&gt;Price&lt;/strong&gt; field. To do this, we can use the &lt;code&gt;setValues​​()&lt;/code&gt; method and update only the field we need.&lt;/p&gt;

&lt;p&gt;Now the order price is updated dynamically when the user changes the number of goods and applies the insurance.&lt;/p&gt;

&lt;h3&gt;How to Navigate Between Forms&lt;/h3&gt;

&lt;p&gt;In each form of our application, we have created the "&lt;strong&gt;Back&lt;/strong&gt;" and "&lt;strong&gt;Next&lt;/strong&gt;" buttons to navigate between tabs.&lt;/p&gt;

&lt;p&gt;The "&lt;strong&gt;Back&lt;/strong&gt;" button will switch the &lt;strong&gt;multiview&lt;/strong&gt; component to the previous module, and the "&lt;strong&gt;Next&lt;/strong&gt;" button to the next one. To get the buttons to work, we need to catch the click events and set the appropriate handlers.&lt;/p&gt;

&lt;p&gt;To handle the click event, the &lt;strong&gt;button&lt;/strong&gt; control has a special &lt;strong&gt;&lt;em&gt;click&lt;/em&gt;&lt;/strong&gt; property.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In the handler of the "&lt;strong&gt;Back&lt;/strong&gt;" button of the user form, we go back to the trade list via its &lt;code&gt;show()&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;goBackCustomHandler&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;trade_list&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;//go to the trade list&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the same handlers of two other forms, we go to the previous module via the &lt;code&gt;back()&lt;/code&gt; method of the &lt;strong&gt;multiview&lt;/strong&gt; widget, which contains the tabs with the forms.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;goBackCustomHandler&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;form_multiview&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;back&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;//go to the previous module&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the handler of the "&lt;strong&gt;Next&lt;/strong&gt;" button, we also use the &lt;code&gt;show()&lt;/code&gt; method to display the desired module, included in the &lt;strong&gt;multiview&lt;/strong&gt; component.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;goNextCustomHandler&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id_of_next_form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In this way we will change tabs dynamically.&lt;/p&gt;

&lt;h3&gt;How to Validate the Forms&lt;/h3&gt;

&lt;p&gt;When the user clicks on the "&lt;strong&gt;Next&lt;/strong&gt;" button and before switching to the next form, we need to validate the current form. This can be done in the "&lt;strong&gt;Next&lt;/strong&gt;" button handler:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;goNextCustomHandler&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id_of_current_form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;()){&lt;/span&gt;
        &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id_of_next_form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here we run the validation of the current form via its &lt;code&gt;validate()&lt;/code&gt; method. It will return true if the validation is successful, and false if not. It should be noted here that the method checks only those form fields for which we applied the rules. Webix allows setting these rules for a separate field via its &lt;a href="https://docs.webix.com/api__ui.text_required_config.html" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;required&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://docs.webix.com/api__ui.text_validate_config.html" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;validate&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; properties, and for the whole form via its &lt;a href="https://docs.webix.com/api__link__ui.form_rules_config.html" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;rules&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; property.&lt;/p&gt;

&lt;p&gt;I hope you still remember that for the required fields we defined the required property. This property adds a red asterisk to the labels of the required fields. By default, such fields are validated by the built-in &lt;code&gt;webix.rules.isNotEmpty&lt;/code&gt; rule and must be filled. If at least one of these fields is not filled in, the validation method will return an error and the fields will be highlighted in red.&lt;/p&gt;

&lt;p&gt;The unvalidated order form will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmll6xgmudyzujgq06tvg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmll6xgmudyzujgq06tvg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If all the required fields of this form are filled in, or the "Delivery Information" section is hidden, the multiview will be switched to the next form.&lt;/p&gt;

&lt;p&gt;Besides the &lt;strong&gt;&lt;em&gt;required&lt;/em&gt;&lt;/strong&gt; property with the default validation rule, we can apply other built-in rules or define our own. Let's set such rules for checking the email and phone number in the user form. And this can be done in the object of the &lt;strong&gt;&lt;em&gt;rules&lt;/em&gt;&lt;/strong&gt; property of the form.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;To check the email address, we use the built-in &lt;code&gt;webix.rules.isEmail&lt;/code&gt; rule, and for the phone number we use our own condition. Since the phone number consists of 11 digits, we will return an error if the entered value length is less than the required one.&lt;/p&gt;

&lt;p&gt;To make the field validation more informative, let's add a hint that will be displayed if the validation method returns an error. For the required fields, we need to specify the &lt;strong&gt;&lt;em&gt;invalidMessage&lt;/em&gt;&lt;/strong&gt; property and set it to the error message.&lt;/p&gt;

&lt;p&gt;The unvalidated user form will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1f28uq7e9bygo85x4vv7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1f28uq7e9bygo85x4vv7.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In case the user navigates to the previous form and then comes back, let's clear the validation markers of the current form. To do this, we can use the &lt;code&gt;clearValidation()&lt;/code&gt; method of the form and call it in the "&lt;strong&gt;Back&lt;/strong&gt;" button handler.&lt;/p&gt;

&lt;h3&gt;How to Make Order&lt;/h3&gt;

&lt;p&gt;In the last payment form, we have created the "&lt;strong&gt;Make order&lt;/strong&gt;" button instead of the "&lt;strong&gt;Next&lt;/strong&gt;" button. This button runs validation and, if successful, collects data from all three forms, clears the current form and displays the main page with the goods list. The handler code will look like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In a real example, the collected data needs to be sent to the server for further processing. But this is the topic of another article.&lt;/p&gt;

&lt;h1&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;You can find the full source code and live demo &lt;a href="https://github.com/serhiipylypchuk1991/book-store-service" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this article, we have detailed how to create forms using the Webix library, and now we know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how to connect the library&lt;/li&gt;
&lt;li&gt;how to describe UI components using JSON syntax&lt;/li&gt;
&lt;li&gt;how to use component methods&lt;/li&gt;
&lt;li&gt;how to set the event handlers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And most importantly, we have learned how to work with Webix forms, apply various controls and use methods for managing the form (collecting and setting data, validation, etc.).&lt;/p&gt;

&lt;p&gt;As you can see, the widget names, their methods and properties are intuitive and easy to use. In fact, this is only a small part of everything that the library can offer. For more detailed information, you can go to the &lt;a href="https://docs.webix.com/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;, which contains a detailed description of all the possibilities with examples.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>html</category>
    </item>
  </channel>
</rss>
