HT for Web Data Model Manual


Design Patterns

Proper use of design patterns can greatly improve the maintainability and scalability of the framework, a good design interface can greatly reduce the amount of user code and improve readability, in favor of the team work of large-scale project development, even do not need to access backend data to complete the unit testing of the front-end component, facilitates data binding and data synchronization for components and models, this will help the developer to further provide WYSIWYG visual development tools, such as Adobe Flash Builder and Microsoft Visual Studio.


In the early GUI design field, Java/Swing, SWT/JFace, Cocoa and Qt are model of the design pattern based on Model View Controller(MVC).


After MVC slowly develop derived Model View Presenter(MVP) design patterns are gradually being adopted by the new GUI framework, such as based on Flash Apache/Flex enterprise application component, and the JGoodies framework encapsulated on the Swing basis. Martin Fowler GUI Architectures analyzes and compares the two design patterns.


In recent years, on the basis of MVP to add the ViewModel layer derive from the Model View ViewModel(MVVM) design pattern, but also by Microsoft new generation of GUI development framework Silverlight/WPF is adopted, including a framework for simplifying HTML and JS data bindings, such as Knockout, also based on the MVVM design pattern.


MVC/MVP/MVVM and other design patterns to facilitate the understanding and classification of different frameworks, any GUI framework in the specific implementation of their own evolution and characteristics, HT overall framework is more like the MVP and MVVM design patterns, but we prefer to call the HT design model Object View Mapping(OVM), analogous to Object Relational Mapping(ORM), which masks the heterogeneity of various view component by facing encapsulation of object mode, employs a unified DataModel data model and SelectionModel selection model that can drive ListView, TreeView, TableView, TreeTableView, GraphView and Graph3dView all HT view components.

The HT Design architecture, users only need to master a unified data-driven interface, not due to the increasement of view component to bring additional learning costs, which is HT easy to master the basic.


The Data type runs through the HT framework and is the most basic data type.

ht.Default.setImage('edit',  'res/edit.png');
ht.Default.setImage('mail',  'res/mail.png');
ht.Default.setImage('readmail',  'res/readmail.png');
ht.Default.setImage('search',  'res/search.png');
ht.Default.setImage('settings',  'res/settings.png');            

function init(){                                
    dataModel = new ht.DataModel();                    
    treeView = new ht.widget.TreeView(dataModel);
    view = treeView.getView();            

    view.className = 'main';
    window.addEventListener('resize',  function (e) {
    },  false);                         

    var inbox = addData('Inbox',  'mail');
    addData('Read Mail',  'readmail',  inbox);                             
    addData('Drafts',  'edit');
    var search = addData('Search Folders',  'search');
    addData('Categorized Mail',  'search',  search);                             
    addData('Large mail',  'search',  search);                             
    addData('UnRead Mail',  'search',  search);                             
    addData('Settings',  'settings');


function addData(name,  icon,  parent){
    var data = new ht.Data();
    data.setParent(parent); // or parent.addChild(data);
    return data;

Data Container

Data container ht.DataModel(following abbrivation DataModel) as the model of load Data type, managing the additions and deletions of Data and the distribution of change events, all components of HT framework to display in the users interface by binding DataModel, as the same time, components would also listening the changing events of DataModel, real-time synchronization between data and user interface, mastering the DataModel operation has mastered the model-driven approach of all the components.

The Data type object is automatically assigned an id attribute inside the construct and can use data.getId() and data.setId(id) gets and sets the, the data object is not allowed to modify the id value after it is added to DataModel and can be quickly found Data objects through data.getDataById(id).

Generally recommended id attribute is automatically assigned by HT, the only sign of user's business meaning can exist in tag attribute, through Data#setTag(tag) function allows any dynamic change tag value, through DataModel#getDataByTag(tag) can find the corresponding data object and support through DataModel#removeDataByTag(tag) delete Data object.

id and tag are all target the only assigned Data object, if search for the not uniqueness attribute can used ht.QuickFinder plug-in.

The use of DataModel requires more attention: Data, which is generally require a parent-child relationship, should be added to the container. Often encountered parent in the container, but children didn't, resulting in components can't see the problems of children, adding parent wouldn't automatically load all descendants, this must be noted.

The Data type has getDataModel() function, data.getDataModel() can obtain the current container information while Data attended in the container, a Data object to be added to multiple DataModel containers at the same time is not allowed.

Through the following firePrppertyChange code snippet can be known, when oldValue equals to newValue, property change event won't be distributed, property change events through handleDataPropertyChange send to DataModel continue to do processing, the subsequent processing include continuing to distribute the event to the property change listener which through addDataPropertyChangeListener add to DataModel.

firePropertyChange: function (property,  oldValue,  newValue) {
    if (oldValue === newValue) {
        return false;
    var e = {
        property: property, 
        oldValue: oldValue, 
        newValue: newValue, 
        data: this
    if (this._dataModel) {
    return true;

Selection Model

ht.SelectionModel manages the Data object in the DataModel model, each DataModel object has a SelectionModel, if you control this SelectionModel then you can control all binding components' object selection state in this DataModel, that means share the same DataModel components default has a selected linkage feature.

If you want some components to be selected without linkage with other components, you can invoke view.setSelectionModelShared(false) so that the view will create a exclusive SelectionModel instance.

In summary there are two ways to get SelectionModel:

The common functions of SelectionModel are as follows:

index = 0;
dataModel = new ht.DataModel();  
selectionModel = dataModel.getSelectionModel();                                           

// monitor data property change event
dataModel.addDataPropertyChangeListener(function (e){                    
    document.getElementById('property').innerText = + '\'s ' + + ' changed';

// monitor data model change event
dataModel.addDataModelChangeListener(function (e){
    var output;
    if(e.kind === 'add'){
        output = + ' added,  ';
    else if(e.kind === 'remove'){
        output = + ' removed,  ';
    else if(e.kind === 'clear'){
        output = 'data model cleared,  ';
    output += 'size:' + dataModel.size();
    document.getElementById('model').innerText = output;

// monitor selection model change event
selectionModel.addSelectionChangeListener(function (e){
    var output = '';
        size = selectionModel.size();                    
    if(size === 0){
        output = 'nothing selected';
    else if(size === 1){
        output = selectionModel.getLastData() + ' selected';
        output = size + ' datas selected';
    document.getElementById('selection').innerText = output;



function addData(){
    var node = new ht.Node();                             
    node.setPosition(50 + index % 12 * 50,  50);
    node.setName('node' + index++);    
    return node;
function removeData(){
    while(selectionModel.size() > 0){

Welcome to contact us