Data binding

juci provides interfaces and properties to bind UI controls and elements to JSON data. juci uses knockout.js framework to observe and trigger dependencies based on the MVVM architecture for maintaining view and data consistency. All controls and elements refer to the default view model available in juci, for dependency detection and updation. Each item on the view model is referred to as a dataset in juci. A dataset can be added to the view model by referencing it with a user defined key. Refer example 1.

juci provides APIs to add, update, get, set dataset. Advanced APIs to add computed dataset, (i.e. a dataset that is generated based on the value of another dataset), adding dataset reference for a form are available. A generic collection can be added to the viewmodel in which each key of the object becomes references for controls. Refer example 2. A user interface built with juci can be control-driven or data-driven. Control-driven interfaces are primarily targeted at simple uses which does not involve too many interconnected data that undergoes constant updation and additions. Control-driven interfaces use control.value() to get and set values on the control. In this case, to get the control, the control can be assigned an ID and referenced through juci.getControl(id) API. For example, simple interfaces such as login, or user information form, etc. can be control-driven.

Data-driven interfaces are targeted at complex usage which involve data that undergo updation and additions. Using the data-bind attribute available on juci controls, the control can be bound to the data, such that any updates in the data is reflected on the control and any changes made by the user on the control is reflected in the data. For example, interfaces such as a task list, form for each task in the list for updation, etc. can be data-driven.

Any change on the dataset defined can be observed by binding listeners to the key defined for the dataset through juci#bindDatasetListener.

Custom data-binding verbs included with juci, which can be used in a similar way as other verbs described in knockout.js

  1. show
  2. enabled
  3. disabled
  4. img
  5. display


Examples

Example 1
Any control or element can be bound to a dataset with that key. For example,
<!--Example 1-->
<div data-juci="text" data-bind="ref: key"></div>
// Example 1
juci.addDataset("key", "value");
Example 2
In the above to access key4, the data-bind reference should be key3().key4, since key3 is also an observable.
// Example 2
juci.addDataset({"key1": "value1", "key2" : [], "key3" : { "key4": "value4"}});
Example 3
If there is more control needed on what part of the dataset needs to be observed for changes, as shown below

// Example 3
juci.setDataset("key3", {"key4": ko.observable("value4")});
juci.addDataset("key3", {"key5":{"key4": ko.observable("value4")}}, true); // key5 will not be observable
Example 4
Another pattern is using the knockout mapping plugin config to determine properties for ignoring, addition, copying, etc. (Example 4)

Further details regarding the usage of mapping plugins can be found in Knockoutjs.

// Example 4
juci.addDataset({'key1': ko.observable('value1'), key2 : ko.observable([]), key3 : { key4: ko.observable('value4')}}, {copy: ["key3"]});
Example 5
An example for computed datasets - Setting options for city based on chosen country in example 5.
<!--Example 5-->
<div data-juci="selectbox" data-label="Country" data-formatter="formatter" data-bind="optionsText: formatter, optionsList: countries, ref: country"></div>
<div data-juci="selectbox" data-label="City" data-bind="optionsList: cities, ref: city"></div>
// Example 5
var obj ={
	"countries": [
		{
			"name": "India",
			"cities": ["Hyderabad", "Chennai", "Bangalore"]
		},
		{
			"name": "USA",
			"cities": ["New York", "Los Angeles", "Miami"]
		},
		{
			"name": "Spain",
			"cities": ["Madrid","Barcelona", "Valencia"]
		}
	],
	"country": "",
	"city": null
};
juci.addDataset(obj);
juci.addComputedDataset("cities", function(){
	var selCountry = this.country();
	this.city(null);
	return selCountry ? selCountry.cities() : [];
});
function formatter(item){ return item.name; }
Example 6
A complex mapping to map iteratively only specific keys of an object using copyRegex and observeRegex
<!--Example 6-->
<div data-juci="list" data-bind="ref: t" data-title="$index"></div>
// Example 6
juci.addDataset("t", [{"a.tt": {"c": "asd"}}], {
	"copyExp": ["t[$i]['a.tt']"] //$i is mapped as the iterator
});
Example 7
Based on Example 6 and extending for the list content view to map only specific fields
<div data-juci="list" data-bind="ref: t" data-title="$index" data-binder-config="getBindingConfig">
	<div data-juci="listcontent">
		<div data-juci="text" data-bind="ref: $data['a.tt'].c"></div>
		<div class="juci_vertical_bbar">
			<button type="submit" data-juci="button">Save</button>
		</div>
	</div>
</div>
// Example 7
function getBindingConfig(){
	return {
		"copyExp": ["['a.tt']"]
	};
}
APIs