# 05. __Component__ [![+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) This page describes the whole implementation of reusable component. [__Learn__ from existing components](https://componentator.com). __Quick navigation:__ - [Definition](#) - [Properties](#) - [Delegates](#) - [Methods](#) - [Usage in HTML](#) - [Configuration](#) - [Data binding](#) ![Component workbench](/download/B20190425T000000015.png) ## Definition The code below describes a simple component definition with default configuration: ```javascript COMPONENT('datetime', 'interval:1000;format:dd.MM.yyyy', function(self, config, cls) { // This is the component scope // self == this // config == this.config // cls {String} auto-generated class name in the form: "ui-COMPONENTNAME" (+v17) var interval; self.readonly(); self.blind(); self.configure = function(name, value, init) { switch (name) { case 'interval': interval && clearInterval(interval); interval = setInterval(self.tick, value); break; case 'format': !init && self.tick(); break; } }; self.tick = function() { self.html(new Date().format(config.format)); }; }); ``` __`+v14.0.0` Declaration with a specific version__: ```javascript // v1 COMPONENT('datetime@1', 'interval:1500;format:dd.MM.yyyy', function(self, config) { // ... }); // v2 COMPONENT('datetime@2', 'interval:500;format:dd.MM.yyyy', function(self, config) { // ... }); ``` __`+v14.0.0` Declaration with multiple versions__: ```javascript // v1 COMPONENT('datetime, datetime@1, datetime@2', 'interval:1000;format:dd.MM.yyyy', function(self, config) { // ... }); ``` - [`COMPONENT()`](@17092620450002mpt0#method-component-) is a global variable ## Properties - [`self._id`](#property-self-_id-) - [`self.caller`](#property-self-caller-) - [`self.config`](#property-self-config-) - [`self.element`](#property-self-element-) - [`self.global`](#property-self-global-) - [`self.id`](#property-self-id-) - [`self.name`](#property-self-name-) - [`self.path`](#property-self-path-) - [`self.pathscope`](#property-self-pathscope-) - [`self.removed`](#property-self-removded-) - [`self.scope`](#property-self-scope-) - [`self.siblings`](#property-self-siblings-) - [`self.template`](#property-self-template-) - [`self.trim`](#property-self-trim-) - [`self.type`](#property-self-type-) ### Property: `self._id` The property contains an internal identificator for this component. - `readonly` - returns `String` ### Property: `self.caller` The property contains a reference to caller/parent of some method executed via `.exec()` - `readonly` - returns `Component` - default `undefined` ### Property: `self.config` The property contains the whole configuration. - `readonly` - returns `Object` ### Property: `self.element` - `readonly` - returns `jQuery Element` ### Property: `self.global` The property contains shared temporary object for all instances of this component. - returns `Object` ### Property: `self.id` The property contains an identifactor for this component. jComponent binds `data-jc-id="ID"` attribute to this property automatically. Otherwise `self.id` is same as `self._id`. - `readonly` - returns `String` ### Property: `self.name` The property contains a name of this component. - `readonly` - returns `String` ### Property: `self.path` The property contains the absolute path for data-binding. This value can be changed via [`self.setPath()`](#method-setpath-). - `readonly` - returns `String` ### Property: `self.pathscope` The property contains a path from parent e.g`
` - `readonly` - returns `Boolean` ### Property: `self.template` The property can contain `url` address to a template or jQuery `selector` which it starts with `.`, `#` or `[`. Template will be stored in this property before is executed `self.make()`. Default value is binded according to `data-jc-template="DEFAULT_VALUE"` attribute. __Examples__: - URL address: `self.template = '/templates/products.html'` - selector: `self.template = '#mytemplate'` - or `
` ### Property: `self.trim` The property can disable auto `trim` string values. It works only with inputs with `data-jc-bind=""` attribute. - returns `Boolean` - default `true` ### Property: `self.type` The property contains a value from `data-jc-type=""` attribute. This `type` describes a data-type for parser or formatter. - returns `String` ## Delegates Delegates are executed on some jComponent actions. Some delegates have to return a value. - [`self.configure(key, value, init, prev)`](#delegate-self-configure-) - [`self.destroy()`](#delegate-self--) - [`self.getter(value)`](#delegate-self-getter-) - [`self.getter2(value)`](#delegate-self-getter2-) - [`self.init()`](#delegate-self-init-) - [`self.knockknock(counter)`](#delegate-self-knockknock-) - [`self.make([template])`](#delegate-self-make-) - [`self.prerender([template])`](#delegate-self-prerender-) - [`self.released(is)`](#delegate-self-released-) - [`self.setter(value, path, type)`](#delegate-self-setter-) - [`self.setter2(value, path, type)`](#delegate-self-setter2-) - [`self.state(type, what)`](#delegate-self-state-) - [`self.validate(value, isInitialValue)`](#delegate-self-validate-) ### Delegate `self.configure()` `optional` The delegate handles a configuration of the component. It's executed after is component initialized and after `self.make()`, or if [`self.reconfigure()`](#method-reconfigure-) is executed manually. Each `key` is processed independently. ```javascript self.configure = function(key, value, init, prev) { // @key {String} // @value {String/Number/Boolean/Object} // @init {Boolean} Is initialization? // @prev {String/Number/Boolean/Object} A previous value switch (key) { case 'required': self.tclass('required', value); break; case 'icon': self.find('.fa').rclass2('fa-').aclass('fa fa-' + value); break; } }; ``` ### Delegate `self.destroy()` `optional` The delegate is executed when the component is removing. ```javascript self.destroy = function() { // Clean up }; ``` ### Delegate `self.getter()` `optional` + `internal` The delegate has an internal implementation and it receives a value from HTML controls like `input`, `select` and `textarea` automatically. It's binded with `data-jc-bind` attribute on the target control. Its implementation is a bit complicated. ```javascript self.getter = function(value) { // @value {String} A value from HTML control }; ``` ### Delegate `self.getter2()` `optional` This delegate has a similar functionality as `self.getter()` but you can use it for your own needs without changing `self.getter()`. ```javascript self.getter2 = function(value) { // @value {Object} A processed value }; ``` ### Delegate `self.init()` `optional` This delegate is executed the only onetime for all same components and jComponent evaluates it if the component is used. If you want to share some data between all instances then you can use [`self.global`](#property-self-global-) property. ```javascript self.init = function() { // It's executed the only one time for all instances of same components }; ``` ### Delegate `self.knockknock()` `optional` This delegate is executed each 60 seconds by jComponent automatically. ```javascript self.knockknock = function(counter) { // @counter {Number} }; ``` ### Delegate `self.make()` `optional` This delegate is executed when the component is creating. If you fill [`self.template`](#property-self-template-) property then the `template` argument will contain obtained data. ```javascript self.make = function(template) { // @template {String} Optional, it contains processed template data }; ``` ### Delegate `self.prerender()` `optional` This delegate can update processed `template` before is executed `self.make()`. It works with filled [`self.template`](#property-self-template-) property only. ```javascript self.prerender = function(template) { // @template {String} // IMPORTANT: it needs to return a modified value return template.replace(/\n/g, '
'); }; ``` ### Delegate `self.released()` `optional` This delegate is executed when the component parent component performs `release` method. For example: `j-Form` component - when the form is closed the component executes `released(true)` for all nested components and when the form is going to visible the component executes `released(false)` for all nested components. ```javascript self.released = function(is) { // @is {Boolean} true = the component is released by parent component, false = isn't released if (is) { // here you can clean-up DOM because e.g. component is hidden } else { // here you can restore previous state because control is visible } }; ``` ### Delegate `self.setter()` `optional` The delegate observes changes in the model according to the defined `path`. It's executed everytime when data changes. Default implementation contains auto-mechanism for HTML inputs like ``, `