jComponent — Total.js
Tags: development, frontend, javascript, totaljs
Published: 2024-04-15 07:02:47

jComponent is a client-side library for UI components from [Total.js.](https://www.totaljs.com/) Currently, it contains more than 300 components, that are all open source and ready to be used in your single page applications. You can also create your components or modify existing components to your requirements.

## Where you can find jComponents?
You can find all jComponents in the [Total.js GitHub repository](https://github.com/totaljs/components) or on the website [componentator.com](https://componentator.com/). There you can find also complementary information about each component, configuration possibilities, methods supported by the component, meta information, if the component supports dark mode and responsiveness, javascript code, CSS styles and example usage with real-time preview. You can play with components there, or easily download it as HTML. If you want to find more information about jComponent or create one by yourself, you can look into [documentation](https://docs.totaljs.com/components/40d03001xw51c/).

## How to use jComponents?
For usage of jComponent in your applications you can download scripts for components or you can use [CDN](https://docs.totaljs.com/components/40d01001on51c/) where are all components updated regularly.

Usage of jComponents is very easy and intuitive, for better understanding I will show you an example of one of the most used components j-Input.

**Code for the usage of j-Input:**

```HTML
<ui-component name="input" path="common.email" config="type:email;required:1" default="'@'">Email</ui-component>
```

**Defined j-Input displayed on the web:**

![j-Input displayed on the web](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mzjm1iy9naoqa6kygn0j.png)

**ui-component** is an HTML tag used for jComponents and it can be used in other elements. In declaration, you can see attributes `name`, `path`, `config` and `default`.

**Attribute name**
This attribute is required for every component. It is the name of the component we want to use, like in the example we want to use **j-Input**, so the name is input (e.g. j-DataGrid — datagrid, j-Box — box, j-Swiper — swiper,…). The name of a component **must be always written in lowercase**.

**Attribute path**
Attribute path is optional, some components don't have to set path. Components work with absolute paths set in the declaration. Data binding works both ways, from model to component and also from component to model. Component will create a listener and it will react to its changes, but to let components know about the change it is necessary to use one of the methods (`SET()`, `UPD()`, `PUSH()`, `INC()`, `EXTEND()`) which will notify all components listening on that path.

There are two ways to set path to your components, with plugins or without.

**Without plugins:**

Usage without plugins is same as in the example code above. Data on the path declared like that can be found at `window.common.email`.

**With plugins:**

```HTML
<ui-plugin path="common">
  // here can be some code
  <ui-component name="input" path="?.email" config="type:email;required:1" default="'@'">Email</ui-component>
  // here can be also some code
</ui-plugin>
```

Usage with plugins can be like shown in this code. The question mark in the path attribute will be replaced with the path from the plugin in the background. It means that the path for this component will be common.email and again can be found at `window.common.email`.

Plugins support also **nested plugins**. For example, if we want to extend our example by an address consisting of country and street, we can do it easily with the nested plugin.

```HTML
<ui-plugin path="common">
  // here can be some code
  <ui-component name="input" path="?.email" config="type:email;required:1" default="'@'">Email</ui-component>
  // here can be also some code
  <ui-plugin path="address">
     <ui-component name="input" path="?.country" config="required:1" default="'Slovakia'">Country</ui-component>
     <ui-component name="input" path="?.city" config="required:1" default="'Banská Bystrica'">City</ui-component>
  </ui-plugin>
</ui-plugin>
```

The question mark in the path of the component or data bind is always replaced with the path from the plugin above it and the plugin path will be extended with the parent plugin path, so the resulting model for a path `common` with default values will look like this:

```JSON
{"address":{"city":"Banská Bystrica","country":"Slovakia"},"email":"@"}
```

**Attribute config**
This attribute is optional and is used for configuration settings for components. You can find all configuration possibilities for each component at [componentator.com](https://componentator.com/components/).

The configuration entry for components has the structure `key1:value1;key2:value2;…`, so as you can see a colon is used to assign a value to a key and a semicolon is used to separate individual keys.

In the examples above I used in configuration for our j-Input keys type with value email and required with value 1. It means that this input will be validated as email and has to be filled in.

Some components have option to use a function in the configuration of jComponent, there is a difference in declaration depending on whether you use the **ui-plugin** or not.

**Without plugin:**

```HTML
<ui-component name="input" path="common.test" config="ricon:ti ti-globe-world;riconclick:click;placeholder:Enter value">Test</ui-component>
```

```js
function click() {
  console.log('click');
};
```


**With plugin:**

With the usage of a plugin you have to declare a function in **PLUGIN** as `exports.click = function() { // some code }`. To call this function from component configuration you have to set it with question mark and slash — `?/click`. By clicking on the icon, the function exports.click will be invoked, because the path for **ui-plugin** and **PLUGIN** name is the same.

```HTML
<ui-plugin path="common">
  <ui-component name="input" path="?.test" config="ricon:ti ti-globe-world;riconclick:?/click;placeholder:Enter value">Test</ui-component>
</ui-plugin>
```

```js
PLUGIN('common', function(exports) {
  exports.click = function() {
    console.log('click');
  };
});
```


Both examples have the same functionality but with different approaches.


![Example of function usage in jComponent configuration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ag5mkdl15x78vfclhe03.gif)

**Attribute default**
Attribute default is optional and is used to set the default value for components that support it.

## Usage of components in other components
Some components use other existing components to extend their functionality. For example, if you want to use **j-Input** with some predefined values in the dropdown, you can do this by combining with **j-Directory**.

```HTML
<ui-component name="LAZY directory" path="null" config="placeholder:Search..."></ui-component>
<ui-plugin path="common">
    <ui-component name="input" path="?.country" config="dirsource:sk|Slovakia,cz|Czech republic,us|USA,uk|United Kingdom,france|France,spain|Spain;placeholder:Enter value">Country</ui-component>
</ui-plugin>
```


![Example of usage component j-Directory with component j-Input](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/975u5bwik2yvomdjpczv.gif)


To make this input dropdown work, we have to declare also j-Directory. Component j-Directory is a **singleton**, which means that you have to declare it only once in your code and then you can use it as many times as you need.

Singletons can be also used independently on other components and they are invoked with the method **SETTER**.

## Example of independent j-Directory:

First of all, we have to declare our j-Directory globally and then I used element `a` for invoking a javascript function.

```HTML
<ui-component name="LAZY directory" path="null" config="placeholder:Search..."></ui-component>
<div><a href="javascript:void(0)">Countries</a></div>
```

In this function, you have to set options for your j-Directory. For example, I set element, items and callback function and then I have to use the **SETTER** method to invoke j-Directory with these options.

```js
$(document).on('click', 'a', function() {
  var opt = {};
  opt.element = $(this);
  
  opt.items = [];
  opt.items.push({ name: 'Slovakia' });
  opt.items.push({ name: 'Czech republic' });
  opt.items.push({ name: 'USA' });
  opt.items.push({ name: 'United Kingdom' });
  opt.items.push({ name: 'France' });
  opt.items.push({ name: 'Spain' });
  
  opt.callback = function(value) {
    console.log('CLICKED:', value);
  };
  
  SETTER('directory/show', opt);
});
```

j-Directory with these settings looks like this on the web.

![Example of independent j-Directory](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2n0jefngsi0y0dr29u9e.gif)

You can see, that I used the word **LAZY** in the name attribute for our j-Directory component. **LAZY** means lazy load, which means that the component will be loaded only when it is needed. It is useful for better performance because if a user doesn't need that component, it won't be loaded. Some other components which support lazy load are j-Datepicker, j-Colorpicker and j-Menu.