# 08. __Data Binding__

[![+Professional Support](https://www.totaljs.com/img/badge-support.svg)](https://www.totaljs.com/support/) [![+Chat with contributors](https://www.totaljs.com/img/badge-chat.svg)](https://messenger.totaljs.com)

Data-Binding is a special feature in jComponent. It can affect DOM element dynamically.

__Topics:__

- [Commands](#)
- [Types of command expressions](#)
- [Advanced usage](#)

---

__Declaration__:

```html
<div data-bind="path.to.property__command1:exp__command2:exp__commandN:exp"></div>
```

### Commands

- [command: `attr`](#)
- [command: `changes`](#)
- [command: `checked`](#)
- [command: `class`](#)
- [command: `click`](#)
- [command: `config`](#)
- [command: `currency`](#)
- [command: `def`](#)
- [command: `delay`](#)
- [command: `disabled`](#)
- [command: `empty`](#)
- [command: `enabled`](#)
- [command: `exec`](#)
- [command: `focus`](#)
- [command: `format`](#)
- [command: `hide`](#)
- [command: `href`](#)
- [command: `html`](#)
- [command: `init`](#)
- [command: `import`](#)
- [command: `invisible`](#)
- [command: `refresh`](#)
- [command: `resize`](#)
- [command: `required`](#)
- [command: `set`](#)
- [command: `setter`](#)
- [command: `show`](#)
- [command: `src`](#)
- [command: `strict`](#)
- [command: `template`](#)
- [command: `text`](#)
- [command: `title`](#)
- [command: `track`](#)
- [command: `tracktype`](#)
- [command: `val`](#)
- [command: `vbindarray`](#)
- [command: `visible`](#)
- [command: `.class_name`](#)

#### command: `attr`

`+v18` command sets a value into the custom attribute:

```html
<div data-bind="some.path__attr data-id"></div>
<div data-bind="some.path__attr data-id:value"></div>

<!-- With nested selector: -->
<div data-bind="some.path__attr data-id b:value"></div>
```

#### command: `changes`

`+v18` command performs all other commands only if the value will be changed. It works with `object` types too.

```html
<div data-bind="some.path__changes__html"></div>
```

#### command: `checked`

Sets the `checked` attribute. Targeted for HTML controls only `input`. Expression must return `Boolean`.

```html
<input data-bind="some.path__checked:value" />
```

#### command: `class`

Toggles specified `class` when the `data-bind` is processed. Epression must be `String` only. Supports multiple classes seperated by empty space.

```html
<div data-bind="some.path__class:hidden" class="hidden">READY</div>

<!-- Or multiple classes: -->
<div data-bind="some.path__class:hidden ready" class="hidden">READY</div>
```

#### command: `click`

`+v17` Executes method when the user clicks on the element.

```html
<div data-bind="some.path__click:link_to_method"></div>

<!-- OR WITHOUT PATH -->
<div data-bind="null__click:link_to_method"></div>

<!-- Replaces ? for a SCOPE PATH -->
<div data-bind="null__click:?/link_to_method"></div>

<script>
	function link_to_method(element, event, value, path) {
		// do something
	}
</script>
```

#### command: `config`

Performs `reconfiguration` for the current jComponent. Expression must return `String` with jComponent configuration or can return `Object`.

```html
<div data-bind="some.path__config:'required:' + (value === true)" data---="textbox">My textbox</div>

<!-- Sets "required" for all nested jComponents -->
<div data-bind="some.path__config [data-jc]:'required:' + (value === true)">
	<div data---="textbox"></div>
	<div data---="dropdown"></div>
	etc..
</div>
```

#### command: `currency`

`+v18` Renders formatted currency. A value in `currency` command is a currency, it's not evaluated and can be used `[value_from_ENV]`.

```html
<div data-bind="some.path.to.number__currency:eur__html"></div>

Additional example with a dynamic currency:
<div data-bind="some.path__html:value.price.currency(value.currency)__track:price,currency"></div>
```

#### command: `def`

Sets the `def` attribute. It's targeted for HTML controls only `input`, `textarea`, `select` and `button`.

```html
String:
<div data-bind="some.path__def:'String'__html:JSON.strignify(value)"></div>

Number:
<div data-bind="some.path__def:100__html:JSON.strignify(value)"></div>

Boolean:
<div data-bind="some.path__def:true__html:JSON.strignify(value)"></div>

Object:
<div data-bind="some.path__def:{}__html:JSON.strignify(value)"></div>

Array:
<div data-bind="some.path__def:[]__html:JSON.strignify(value)"></div>
```

#### command: `delay`

Delays a binding for 2 seconds. Must be a number which represents `milliseconds`.

```html
<input data-bind="some.path__val:value__delay:2000" />
```

#### command: `disabled`

Sets the `disabled` attribute. It's targeted for HTML controls only `input`, `textarea`, `select` and `button`. Expression must return `Boolean`.

`+v17` extends `disabled` command for components. Now the library can perform reconfigure with `disabled:true/false` command.

```html
<input data-bind="some.path__disabled:value" />
```

#### command: `empty`

`+v17` Sets an `empty` HTML to the current element when is the value `null` or `undefined` or __empty string__. 

```html
<div data-bind="some.path__empty:---"></div>
```

#### command: `enabled`

`+v16` Sets the `enabled` attribute. It's targeted for HTML controls only `input`, `textarea`, `select` and `button`. Expression must return `Boolean`.

`+v17` extends `enabled` command for components. Now the library can perform reconfigure with `disabled:true/false` command.

```html
<input data-bind="some.path__enabled:value" />
```

#### command: `exec`

Expression must be a link to a function. This function will be executed if the `data-bind` __path__ will be changed.

```html
<div data-bind="some.path__exec:myfunction"></div>

<script>
	function myfunction(value, path, element) {
		console.log('VALUE HAS BEEN CHANGED:', value);
	}
</script>
```

#### command: `focus`

`+v18` supports `focus` command which can contain a __jQuery selector__ which will perform `.focus()`. Example:

```html
<div data-bind="some.path__focus:input">
	<input type="text" value="Focused!" />
</div>
```

#### command: `format`

`+v17` enables a specific format for `Date` or `Number` types.

```html
<div data-bind="some.path.date__html__format:dd.MM.yyyy"></div>

// Or link to environment variable
<div data-bind="some.path.date__html__format:[date]"></div>

// +v17 supports path to value in the form of environment variables
<div data-bind="some.path.date__html__format:[.path.to.property]"></div>
```

#### command: `hide`

Toggles `hidden` class. Expression must return `Boolean`.

```html
<div data-bind="some.path__hide:value"></div>
<div data-bind="some.path__hide:value !== 'users'"></div>
```

#### command: `href`

Sets `href` attribute. It's targeted for links `<a>` only. Expression must return `String`.

```html
<div data-bind="some.path__href:value"></div>
```

#### command: `html`

Sets the value as the HTML content. Expression must return `String`.

```html
<div data-bind="some.path__html:value"></div>
<div data-bind="some.path__html:value.toUpperCase()"></div>
```

#### command: `init`

`+v17` Executes method when the binder is initialized. This command is performed only one time.

```html
<div data-bind="some.path__init:link_to_method"></div>

<script>
	function link_to_method(value, path, element) {
		// do something
	}
</script>
```

#### command: `import`

Performs `IMPORT()`. Expression must be __URL address__ `String` or (`+v16`) `value` must return a valid URL adress.

This command imports each resource only one time.

```html
<div data-bind="some.path__import:https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></div>

<div data-bind="some.path__import:value"></div>
```

`+v18` adds a support for `<script type="text/html">`:

```html
<div data-bind="some.path__show__import:true">
	<script type="text/html">
		The content will be evaluated when the element will be visible.
	</script>
</div>
```

`+v18` supports __ENV__

```html
<script>
	ENV('mycdn', 'https://totaljs.com');
</script>

<div data-bind="some.path__import:[mycdn]/js/app.js"></div>
```

#### command: `invisible`

`+v16` sets `invisible` class to this element if the condition is valid. `invisible` class is a part of `spa.min.css` and it's declaration is `.invisible { visibility: hidden; }`. __Usage__:

```html
<div data-bind="some.path__invisible:value == true"></div>
```

#### command: `refresh`

`+v18` Expression must be a link to a function. This function will be executed if __the element is visible__ and the `data-bind` __path__ will be changed.

```html
<div data-bind="some.path__refresh:myfunction"></div>

<script>
	function myfunction(value, path, element) {
		console.log('VALUE OF VISIBLE ELEMENT HAS BEEN CHANGED:', value);
	}
</script>
```

#### command: `resize`

`+v18` executes `resize` method in all nested components. IMPORTANT: __the element must visible__.

#### command: `required`

`+v18` performs `required` reconfiguration for the current element component. It expects boolean value type.

```html
<div data---="input__?.company" data-bind="?.iscompany__required">Company name</div>
```

#### command: `set`

`+v18` can set a value to a component. It will works with `vbindarray` too, but only in readonly mode.

- `.` dot in component's path allows to bind a value from `data-bind`
- `set` command is very important for binding

```html
<div data-bind="some.path__set" data---="textbox__.__required:1"></div>

OR

<div data-bind="some.path__set:value.toUpperCase()" data---="textbox__.__required:1"></div>
```

#### command: `setter`

`+v16` performs `element.SETTER()` for nested components.

```html
<div data-bind="some.path__setter:'datagrid','resize'"></div>
<!-- performs: element.SETTER('datagrid', 'resize') -->

<div data-bind="some.path__setter:true,'datagrid','resize'"></div>
<!-- performs: element.SETTER(true, 'datagrid', 'resize') -->
```

#### command: `show`

Toggles `hidden` class. Expression must return `Boolean`.

```html
<div data-bind="some.path__show:value"></div>
<div data-bind="some.path__show:value === 'users'"></div>
```

#### command: `src`

Sets `src` attribute, targeted for `<img`. Expression must return `String`.

```html
<div data-bind="some.path__src:value"></div>
```

#### command: `strict`

This command performs a strict comparing of path. Must be __without expression__.

```html
<div data-bind="myobj.address__strict__html:JSON.stringify(value)"></div>
```

- allowed paths `myobj` or `myobj.address`
- another paths like `myobj.customer` or something else doesn't affect this binder

#### command: `template`

Compiles HTML content as a Tangular template. Can be defined __without expression__. `+v17` expression can contain a jQuery `selector` which enables Virtual DOM comparing for content.

```html
<div data-bind="some.path__template">
	<script type="text/html">
		<div>{{ value.name }}</div>
		<div>{{ value.price | format(2) }}</div>        
	</script>
</div>

<!-- +v17 With Virtual DOM differ -->
<div data-bind="some.path__template:.product">
	<script type="text/html">
		<div class="product">
			<div>{{ value.name }}</div>
			<div>{{ value.price | format(2) }}</div>        
		</div>
	</script>
</div>

<!-- +v18 With custom template -->
<div data-bind="some.path__template:{jQuery selector}"></div>

<!-- +v18 With custom template and virutal dom -->
<div data-bind="some.path__template:.product {jQuery selector}"></div>
```

- `value` represents Tangular model

__Virtual DOM__: Template is compiled to Virtual DOM and then it's compared with current DOM. This feature can improve rendering (blinking) when the content is re-rendering.

#### command: `text`

Sets a value as the TEXT content (HTML markup will be escaped). Expression must return `String`.

```html
<div data-bind="some.path__text:value"></div>
<div data-bind="some.path__text:value.toUpperCase()"></div>
```

#### command: `title`

Sets `title` attribute.

```html
<div data-bind="some.path__title:value"></div>
```

#### command: `track`

Enables a strict path comparison for defined paths separated by comma (use a `field` name without parent path). Binder will render the content below if the main path `object` will be changed or specific field (`name` or `price`) will be changed.

```html
<div data-bind="some.path__template__track:name,price">
	<script type="text/html">
		<h1>{{ value.name }}</h1>
		<div>Price: {{ value.price | format(2) }} EUR</div>
	</script>
</div>
```

#### command: `tracktype`

Tracks only changes according to defined `SET()` types. A value can contain multiple values separated by comma.

```html
<div data-bind="some.path__html__tracktype:2"></div>

<script>
	// Will be binded
	SET('some.path', 'Value', 2);

	// Won't be binded
	SET('some.path', 'Value', 1);
</script>
```

Internal types:

- `0` init value
- `1` manually via e.g. `SET()`
- `2` by input
- `3` default value

#### command: `val`

Sets `value` for the input/textarea/select. Expression must return `String`.

```html
<input data-bind="some.path__val:value" />
```

#### command: `vbindarray`

`+v17` This is very special command. It has same functionality like `template` but the `<script type="text/html"` must contain `VBINDARRAY` template. [Read more about `VBINDARRAY` here](#virtual-binder-vbindarray).

```html
<div data-bind="some.path.to.array__vbindarray">
	<script type="text/html">
		<div data-bind=".name__html b">Name: <b></b></div>
		<p data-bind=".description__html"></p>
	</script>
</div>
```

#### command: `visible`

`+v16` sets `invisible` class to this element if the condition is __not valid__. `invisible` class is a part of `spa.min.css` and it's declaration is `.invisible { visibility: hidden; }`. __Usage__:

```html
<div data-bind="some.path__visible:value !== false"></div>
```

#### command: `.class_name`

Toggles `.class_name` if the expression returns `true`. You can use multiple `.class_name` commands.

```html
<div data-bind="some.path__.animate:value > 100"></div>

Multiple:
<div data-bind="some.path__.animate1:value > 100__.animate2:value > 1000"></div>
```

## Types of command expressions

You can use multiple types of command expressions. You need to choose what suits is for you. In most cases `value` argument contains the real value from a model according to the `data-bind` path. :warning: __IMPORTANT:__ `click` command uses other order of arguments.

__Arrow function in the form__:

```html
COMMAND:(value,path,jQueryElement)=>value.toUpperCase()

<or>

COMMAND:n=>n.toUpperCase()
```

__Direct value__:

```html
COMMAND:value.toUpperCase()

<or>

COMMAND:value

<or>

COMMAND:value > 10
```

__Link to method__:

```html
COMMAND:upper_value
```
- but `function upper_value(value, path, element)` must be defined in the window scope

## Advanced usage

- [Good to know](#)
- [Linking commands to same expression](#)
- [Extending command by adding a selector](#)
- [Nullable values](#)
- [Multiple watchers](#)
- [jComponent scopes](#)
- [Inline helpers](#)
- [Using data-bind in jComponents](#)
- [Disable Data Binding](#)
- [Refreshing Data Binding](#)
- [Less code in Data Binding](#)
- [Virtual binder: VBIND](#)
- [Virtual binder: VBINDARRAY](#)

### Good to know

`+v16` Most of commands are performend when the __element is visible__ --> in other words: the __command__ `show` must return `true` or `hide` must return `false`.

If you want to evaluate a command for hidden element then you can extend command by adding `~` before the name of command, for example:

```html
<div data-bind="some.path__~setter:'datagrid','resize'">
	...
</div>
```

### Linking commands to same expression

You can link commands to same expression with help of `+` char with spaces on both sides.

```html
<div data-bind="path.to.property__COMMAND + COMMAND + COMMAND:VALUE"></div>
<div data-bind="user.age__visible + .selected:age => age > 18__html:value"></div>
```

### Extending command by adding a selector

You can extend most of commands by adding a custom __jQuery selector__.

```html
Declaration:
<div data-bind="some.path__html JQUERY_SELECTOR:value"></div>

Usage:
<div data-bind="some.path__html h1:value__show:value">
	<h1></h1>
</div>
```

### Nullable values

Nullable / Undefined values can be handled easily. Just use `!COMMAND` and evaluating will be performed if the value won't be `null` or `undefined`.

```html
<div data-bind="user.name__!html:value.toUpperCase()"></div>
```

### Multiple watchers

You can define multiple data-bind paths in the same HTML element. Paths must be divided by this `__|__` phrase. For example:

```html
<div data-bind="path.to.property1__command:expression__|__path.to.property2__command:expression__|__path.to.property3__command:expression"></div>
```

### jComponent scopes

You can use `data-bind` in jComponent scopes, but you need to defined `?` (question mark) on the start of `data-bind` path. Question mark `?` will be replaced for a scope path.

```html
<div data-bind="?.property__html:value"></div>
```

`+v17` supports scope in command values:

```html
<div data-bind="?.property__html:?/render"></div>
<!-- WILL BE COMPILED TO -->
<div data-bind="SCOPEPATH.property__html:SCOPEPATH/render"></div>
```

__Good to know__:

- it will work only if the jComponent scope will contain some jComponents

### Inline helpers

Data-Binding supports inline helpers:

```html
1. Direct assignment
<div data-bind="form.name --> (value || '').toUpperCase()__html:value"></div>

2. With arrow function
<div data-bind="form.name --> n => (n || '').toUpperCase()__html:value"></div>

3. Plugins
<div data-bind="form.name --> plugin/method(value)__html:value"></div>
```

### Using data-bind in jComponents

The example below will work in component's scope only.

```html
Binds a value according to the data-jc-path attribute.
It works in the component scope only.

<div data-bind="@__COMMAND + COMMAND + COMMAND:VALUE"></div>

Binds a component config.
It works in component scope only.

<div data-bind="@config__COMMAND + COMMAND + COMMAND:VALUE"></div>

Binds a value defined via component.data('property', value).
It works in the component scope only.

<div data-bind="@property__COMMAND + COMMAND + COMMAND:VALUE"></div>
```

`+v17` supports private binding methods:

```html
<div data-bind="@__html:@method_in_component"></div>
```

### Less code in Data Binding

`+v17` supports shorter commands:

```html
<div data-bind="property__show"></div>
<!-- IS SAME AS -->
<div data-bind="property__show:value"></div>

<div data-bind="property__html"></div>
<!-- IS SAME AS -->
<div data-bind="property__html:value"></div>

<div data-bind="property__html__show"></div>
<!-- IS SAME AS -->
<div data-bind="property__html:value__show:value"></div>
```

### Disable Data Binding

`+v17` supports disabling of data binding:

```html
<div id="myelement" data-bind="property__html:value"></div>

<script>
	$('#myelement').binder().disabled = true;
</script>
```

### Refreshing Data Binding

`+v17` supports refreshing of data-bind. It can be helpful for specific components and behaviours.

```html
<div id="myelement" data-bind="property__html:value"></div>

<script>
	$('#myelement').binder().refresh();
</script>
```

### Virtual binder: VBIND

`+v16` supports this method. Virtual binder `VBIND` is a special thing and it can bind data from a custom model which doesn't need to be defined in the window scop. Compiled element doesn't need to be a part of DOM.

- paths __must start__ with (dot) `.path`
- it expects a custom object

```javascript
// VBIND(template);
var obj = VBIND('<div data-bind=".name__html:value"></div>');

// Sets a model
obj.set({ name: 'Peter' });

// Sets a specific value with path
obj.set('name', 'Peter');

// +v18 Updates a specific path
obj.upd(path);

// +v18 Updates entire object
obj.upd();

// Removes the binder
obj.remove();

// jQuery element
obj.element.html(); // <div>PETER</div>

// Attachs element into the DOM
$(document.body).append(obj.element);
```

`+v17` supports private binding methods:

```javascript
var obj = VBIND('<div data-bind=".name__html:.mymethod"></div>');

obj.mymethod = function(value, path, el) {
	// this === jQuery element
	return 'VALUE_FOR_COMMAND';
};

// Sets a model
obj.set({ name: 'Peter' });
```

#### Obtaining `VBIND` instance from element

```javascript
var vbind = element.vbind();
vbind.set(YOUR_OBJECT);
```

### Virtual binder: VBINDARRAY

`+v16` supports this method. `VBINDARRAY` prepares a `template` as `VBIND` object and it renders items/templates very effective according to the array. It's someting similiar like Virtual DOM.

- paths __must start__ with (dot) `.path` in the template
- each `VBIND` element will contain `data-index` attribute with the item array index

```javascript
// VBINDARRAY(template, target_element);
var obj = VBINDARRAY('<div data-bind=".name__html:value"></div>', document.body);
obj.set([{ name: 'Peter' }, { name: 'Anna' }, { name: 'Lucia' }]);
```

`+v17` supports private binding methods:

```javascript
var obj = VBINDARRAY('<div data-bind=".name__html:.mymethod"></div>', document.body);

obj.mymethod = function(value, path, el) {
	// this === jQuery element
	return 'VALUE_FOR_COMMAND';
};

// Possibilities:
// obj.set(index, item);
// obj.set(array);

// Sets a model
obj.set([{ name: 'Peter' }, { name: 'Anna' }, { name: 'Lucia' }]);

// v18 additional methods:
// obj.upd(index);
// obj.upd();
```

#### Obtaining `VBINDARRAY` instance from element

```javascript
var vbindarray = element.vbindarray();
vbindarray.set([YOUR_ARRAY]);
```