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
<!--Example 1-->
<div data-juci="text" data-bind="ref: key"></div>
// Example 1
juci.addDataset("key", "value");
// Example 2
juci.addDataset({"key1": "value1", "key2" : [], "key3" : { "key4": "value4"}});
// 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
juci.addDataset({'key1': ko.observable('value1'), key2 : ko.observable([]), key3 : { key4: ko.observable('value4')}}, {copy: ["key3"]});
<!--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-->
<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
});
<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']"]
};
}