ALLOY WIDGETS
Improving code re-use through a library of bespoke UI
                    components.




                     TiConf.eu
            Martin Hudson, Jonti Hudson
                   February 2013
WHAT IS A WIDGET?

A self-contained bespoke UI component that
holds all the logic associated with its use.
WHAT IS A WIDGET?

A self-contained bespoke UI component that
holds all the logic associated with its use.

•   Create a re-usable library across multiple
    projects
WHAT IS A WIDGET?

A self-contained bespoke UI component that
holds all the logic associated with its use.

•   Create a re-usable library across multiple
    projects

•   Create components that manage cross-
    platform differences (e.g. a table edit / delete
    component)
WHAT IS A WIDGET?

A self-contained bespoke UI component that
holds all the logic associated with its use.

•   Create a re-usable library across multiple
    projects

•   Create components that manage cross-
    platform differences (e.g. a table edit / delete
    component)

•   Improve readability of code
WHAT IS A WIDGET?

A self-contained bespoke UI component that
holds all the logic associated with its use.

•   Create a re-usable library across multiple
    projects

•   Create components that manage cross-
    platform differences (e.g. a table edit / delete
    component)

•   Improve readability of code

•   Improve reliability due to re-use of tested
    components.
WHAT IS A WIDGET?
App                         Widget




             Multiple widgets in the same window...
WHAT IS A WIDGET?
App                          Widget




             ... or multiple instances of the same
             widget
A CUSTOM TABLE VIEW WIDGET
An example of building a cross-platform widget that encapsulates common
functionality but utilises platform specific behaviour.
CREATING A WIDGET
To create a new widget, right click the project name in the Titanium Studio
project view... and select New → Alloy Widget.
CREATING A WIDGET
To create a new widget, right click the project name in the Titanium Studio
project view... and select New → Alloy Widget.




Use a “Reverse domain” naming convention to ensure widget names are not
replicated when you share widgets with others.
WIDGET FILE STRUCTURE
A widgets folder is created with Controllers, Styles and Views sub-directories.




Note the absence of Models – this is because the main app should handle
data storage
USING A WIDGET
In the main app, we will call the newly created widget using the “Require” tag.

          App – index.xml                                Widget – widget.xml

  <Alloy>                                            <Alloy>
  <Window class="container">                            <TableView id="table"></TableView>
   <Require type="widget"                            </Alloy>
    src="co.mobiledatasystems.customEditableTable"
  id="table1">
   </Require>
   <Button id="btnEdit" title="Allow Editing"
  onClick="btnEdit_click_Event">
   </Button>
  </Window>
  </Alloy>
USING A WIDGET
In the main app, we will call the newly created widget using the “Require” tag.

          App – index.xml                                Widget – widget.xml

  <Alloy>                                            <Alloy>
  <Window class="container">                            <TableView id="table"></TableView>
   <Require type="widget"                            </Alloy>
    src="co.mobiledatasystems.customEditableTable"
  id="table1">
   </Require>
   <Button id="btnEdit" title="Allow Editing"
  onClick="btnEdit_click_Event">
   </Button>
  </Window>
  </Alloy>




Note we specify that we want a widget and reference the name of our new
widget. Alloy knows where to find it.
USING A WIDGET
In the main app, we will call the newly created widget using the “Require” tag.

          App – index.xml                                Widget – widget.xml

  <Alloy>                                            <Alloy>
  <Window class="container">                            <TableView id="table"></TableView>
   <Require type="widget"                            </Alloy>
    src="co.mobiledatasystems.customEditableTable"
  id="table1">
   </Require>
   <Button id="btnEdit" title="Allow Editing"
  onClick="btnEdit_click_Event">
   </Button>
  </Window>
  </Alloy>




 In the widget, we specify the UI components we want to expose. In our
 case it is only a TableView.
STYLING
          App – index.tss                Widget – widget.tss

".container": {
   backgroundColor:"white"
},
"#table1": {
   left: '10dp',
   right: '10dp',
   top: '20dp',
   bottom:'80dp'
},
"#btnEdit": {
   bottom:'10dp',
   left:'20dp',
   right:'20dp',
   height:'45dp'
}




We have referenced our instance of the
widget “table1” in index.xml
STYLING
           App – index.tss                  Widget – widget.tss

 ".container": {
    backgroundColor:"white"
 },
 "#table1": {
    left: '10dp',
    right: '10dp',
    top: '40dp',
    bottom:'80dp'
 },
 "#btnEdit": {
    bottom:'10dp',
    left:'20dp',
    right:'20dp',
    height:'45dp'
 }




Note, where possible, do all the styling of
widget components in the main app. This
ensures maximum re-usability across projects.
CONTROLLERS - INITIALISE
           App – index.tss                   Widget – widget.js
                                      //copy the arguments passed in to the widget via.
 ".container": {                      the xml and tss parameters
    backgroundColor:"white"
 },                                   var _args = arguments[0] || {};
 "#table1": {                         var editable = null;
    left: '10dp',
    right: '10dp',                    if(OS_ANDROID){
    top: '40dp',                      editable = false;
    bottom:'80dp'                     };
 },
                                      //get each element set in the widget's xml or tss
 "#btnEdit": {
                                      parameters
    bottom:'10dp',
    left:'20dp',
                                      Ti.API.info(JSON.stringify(_args));
    right:'20dp',
    height:'45dp'                     //iterate round all the parameters we have passed
 }                                    in

                                      for (var key in _args) {
                                        if (_args.hasOwnProperty(key)) {

In the widget's controller we can     //checks key is a direct property of _args, not

access all the parameters passed in   somewhere down the object tree


using the arguments[] array.                if(OS_ANDROID){
                                        	     switch (key){
CONTROLLERS - INITIALISE
           App – index.tss                   Widget – widget.js
                                      //copy the arguments passed in to the widget via.
 ".container": {                      the xml and tss parameters
    backgroundColor:"white"
 },                                   var _args = arguments[0] || {};
 "#table1": {                         var editable = null;
    left: '10dp',
    right: '10dp',                    if(OS_ANDROID){
    top: '40dp',                      editable = false;
    bottom:'80dp'                     };
 },
                                      //get each element set in the widget's xml or tss
 "#btnEdit": {
                                      parameters
    bottom:'10dp',
    left:'20dp',
                                      Ti.API.info(JSON.stringify(_args));
    right:'20dp',
    height:'45dp'                     //iterate round all the parameters we have passed
 }                                    in

                                      for (var key in _args) {
                                        if (_args.hasOwnProperty(key)) {

In the widget's controller we can     //checks key is a direct property of _args, not

access all the parameters passed in   somewhere down the object tree


using the arguments[] array.                if(OS_ANDROID){
                                        	     switch (key){
CONTROLLERS - INITIALISE
           App – index.tss                     Widget – widget.js
                                         //iterate round all the parameters we have passed
 ".container": {
                                         in
    backgroundColor:"white"
 },
                                         for (var key in _args) {
 "#table1": {
                                           if (_args.hasOwnProperty(key)) {
    left: '10dp',
    right: '10dp',
                                         //checks key is a direct property of _args, not
    top: '40dp',
                                         somewhere down the object tree
    bottom:'80dp'
 },
                                               if(OS_ANDROID){
 "#btnEdit": {
                                            	    switch (key){
    bottom:'10dp',
                                            	  	     case 'editing':
    left:'20dp',
                                            	  	     	    editable = _args[key];
    right:'20dp',
                                            	  	     	    break;
    height:'45dp'
                                            	  	     case 'moving': break; //android
 }
                                         doesn't recognise this property
                                            	  	     default:

We can read each parameter passed in        	

                                            	
                                               	

                                                 }
                                                     	    $.table[key] = _args[key];


and process them appropriately. In our      	

                                            	
                                               } else {
                                               	     $.table[key] = _args[key];
example “editable” and “moving” are         	  };
                                            };
iOS specific. We will set a local         };

variable in the case of Android.
CONTROLLERS - INITIALISE
           App – index.tss                     Widget – widget.js
                                         //iterate round all the parameters we have passed
 ".container": {
                                         in
    backgroundColor:"white"
 },
                                         for (var key in _args) {
 "#table1": {
                                           if (_args.hasOwnProperty(key)) {
    left: '10dp',
    right: '10dp',
                                         //checks key is a direct property of _args, not
    top: '40dp',
                                         somewhere down the object tree
    bottom:'80dp'
 },
                                               if(OS_ANDROID){
 "#btnEdit": {
                                            	    switch (key){
    bottom:'10dp',
                                            	  	     case 'editing':
    left:'20dp',
                                            	  	     	    editable = _args[key];
    right:'20dp',
                                            	  	     	    break;
    height:'45dp'
                                            	  	     case 'moving': break; //android
 }
                                         doesn't recognise this property
                                            	  	     default:

We can read each parameter passed in        	

                                            	
                                               	

                                                 }
                                                     	    $.table[key] = _args[key];


and process them appropriately. In our      	

                                            	
                                               } else {
                                               	     $.table[key] = _args[key];
example “editable” and “moving” are         	  };
                                            };
iOS specific. We will set a local         };

variable in the case of Android.
CONTROLLERS – CALLING FUNCTIONS
           App – index.js                                Widget – widget.js
$.index.open();                                     //custom method we expose to set the table's
                                                    data
var editMode = false;                               exports.setData = function(rows /*Ti.UI.Row*/){
                                                       $.table.setData(rows);
//create some data to put in the table              };
var rows = [];
for(var i=0;i<10;i++){                              //custom method we expose to allow the table to
rows.push(Ti.UI.createTableViewRow({title:'Row      be editable
number ' + i}));                                    exports.editing = function(edit /*bool*/){
};                                                     if(OS_IOS){
$.table1.setData(rows); //call the "setData"              $.table.editing = edit; //allow row
method we created in the widget                     editing on iPhone & iPad
                                                       } else {
//toggle the "editable" mode of the table                 editable = edit;
function btnEdit_click_Event(){                        };
   if(editMode){                                    };
      $.btnEdit.title = "Allow Editing";
      editMode = false;
   } else {                                      Using the commonJS framework, we
      $.btnEdit.title = "Cancel Editing";
      editMode = true;                           can expose functions in the widget. In
   };
   $.table1.editing(editMode); //call the        our example we expose “setData” so
"editing" method we created in the widget
};
                                                 we can populate the table after the
                                                 widget has created it.
CONTROLLERS – CALLING FUNCTIONS
           App – index.js                                Widget – widget.js
$.index.open();                                     //custom method we expose to set the table's
                                                    data
var editMode = false;                               exports.setData = function(rows /*Ti.UI.Row*/){
                                                       $.table.setData(rows);
//create some data to put in the table              };
var rows = [];
for(var i=0;i<10;i++){                              //custom method we expose to allow the table to
rows.push(Ti.UI.createTableViewRow({title:'Row      be editable
number ' + i}));                                    exports.editing = function(edit /*bool*/){
};                                                     if(OS_IOS){
$.table1.setData(rows); //call the "setData"              $.table.editing = edit; //allow row
method we created in the widget                     editing on iPhone & iPad
                                                       } else {
//toggle the "editable" mode of the table                 editable = edit;
function btnEdit_click_Event(){                        };
   if(editMode){                                    };
      $.btnEdit.title = "Allow Editing";
      editMode = false;
   } else {                                      Using the commonJS framework, we
      $.btnEdit.title = "Cancel Editing";
      editMode = true;                           can expose functions in the widget. In
   };
   $.table1.editing(editMode); //call the        our example we expose “setData” so
"editing" method we created in the widget
};
                                                 we can populate the table after the
                                                 widget has created it.
CONTROLLERS – CALLING FUNCTIONS
           App – index.js                                Widget – widget.js
$.index.open();                                     //custom method we expose to set the table's
                                                    data
var editMode = false;                               exports.setData = function(rows /*Ti.UI.Row*/){
                                                       $.table.setData(rows);
//create some data to put in the table              };
var rows = [];
for(var i=0;i<10;i++){                              //custom method we expose to allow the table to
rows.push(Ti.UI.createTableViewRow({title:'Row      be editable
number ' + i}));                                    exports.editing = function(edit /*bool*/){
};                                                     if(OS_IOS){
$.table1.setData(rows); //call the "setData"              $.table.editing = edit; //allow row
method we created in the widget                     editing on iPhone & iPad
                                                       } else {
//toggle the "editable" mode of the table                 editable = edit;
function btnEdit_click_Event(){                        };
   if(editMode){                                    };
      $.btnEdit.title = "Allow Editing";
      editMode = false;
   } else {
      $.btnEdit.title = "Cancel Editing";
      editMode = true;                           Here, the main app is responding to a
   };
   $.table1.editing(editMode); //call the        button click event and changing the
"editing" method we created in the widget
};
                                                 editable state in the widget.
CONTROLLERS – CALLING FUNCTIONS
           App – index.js                                Widget – widget.js
$.index.open();                                     //custom method we expose to set the table's
                                                    data
var editMode = false;                               exports.setData = function(rows /*Ti.UI.Row*/){
                                                       $.table.setData(rows);
//create some data to put in the table              };
var rows = [];
for(var i=0;i<10;i++){                              //custom method we expose to allow the table to
rows.push(Ti.UI.createTableViewRow({title:'Row      be editable
number ' + i}));                                    exports.editing = function(edit /*bool*/){
};                                                     if(OS_IOS){
$.table1.setData(rows); //call the "setData"              $.table.editing = edit; //allow row
method we created in the widget                     editing on iPhone & iPad
                                                       } else {
//toggle the "editable" mode of the table                 editable = edit;
function btnEdit_click_Event(){                        };
   if(editMode){                                    };
      $.btnEdit.title = "Allow Editing";
      editMode = false;
   } else {
      $.btnEdit.title = "Cancel Editing";
      editMode = true;                           Here, the main app is responding to a
   };
   $.table1.editing(editMode); //call the        button click event and changing the
"editing" method we created in the widget
};
                                                 editable state in the widget.
CONTROLLERS – HANDLING EVENTS
             App – index.js                                 Widget – widget.js
  $.table1.addEventListener('delete', function(r){    //create a handlers object that will contain
  Ti.API.info('row deleted: ' + JSON.stringify(r));   references to functions
  var dialog = Ti.UI.createAlertDialog({              var handlers = {};
      message: r.row.title,
      title: 'Deleted'                                //assign some functions that do nothing.
    });                                               handlers.click = function(r){};
    dialog.show();                                    handlers.deleteRow = function(r){};
  });
                                                      //expose a function that can pass in a reference
                                                      to an external function and assign the reference
In the widget we create an                            to the appropriate handler.

“addEventListener” function that has                  exports.addEventListener = function(listenerName,
                                                      listenerFunction){
two parameters, the name of the event                    switch (listenerName){
                                                            case 'click' :
and a reference to the function it will                        handlers.click = listenerFunction;
                                                               break;
call in the main app.                                       case 'delete' :
                                                               handlers.deleteRow = listenerFunction;
                                                               break;

We assign the reference to a                          };
                                                         };


“handlers” object we created in the                   if(OS_IOS){
widget.                                                  $.table.addEventListener('delete',
                                                      function(r){
CONTROLLERS – HANDLING EVENTS
             App – index.js                                 Widget – widget.js
  $.table1.addEventListener('delete', function(r){    //create a handlers object that will contain
  Ti.API.info('row deleted: ' + JSON.stringify(r));   references to functions
  var dialog = Ti.UI.createAlertDialog({              var handlers = {};
      message: r.row.title,
      title: 'Deleted'                                //assign some functions that do nothing.
    });                                               handlers.click = function(r){};
    dialog.show();                                    handlers.deleteRow = function(r){};
  });
                                                      //expose a function that can pass in a reference
                                                      to an external function and assign the reference
                                                      to the appropriate handler.
                                                      exports.addEventListener = function(listenerName,
                                                      listenerFunction){
                                                         switch (listenerName){
In the main app we call the                                 case 'click' :

“addEventListener” function, passing in                        handlers.click = listenerFunction;
                                                               break;

the name of the listener and defining                        case 'delete' :
                                                               handlers.deleteRow = listenerFunction;
the function we want to execute when                           break;
                                                         };
the even is fired.                                     };

                                                      if(OS_IOS){
                                                         $.table.addEventListener('delete',
                                                      function(r){
CONTROLLERS – HANDLING EVENTS
             App – index.js                                 Widget – widget.js
  $.table1.addEventListener('delete', function(r){    //assign some functions that do nothing.
  Ti.API.info('row deleted: ' + JSON.stringify(r));   handlers.click = function(r){};
  var dialog = Ti.UI.createAlertDialog({              handlers.deleteRow = function(r){};
      message: r.row.title,
      title: 'Deleted'                                //expose a function that can pass in a reference
    });                                               to an external function and assign the reference
    dialog.show();                                    to the appropriate handler.
  });                                                 exports.addEventListener = function(listenerName,
                                                      listenerFunction){
                                                         switch (listenerName){
                                                            case 'click' :
                                                               handlers.click = listenerFunction;
                                                               break;
                                                            case 'delete' :
                                                               handlers.deleteRow = listenerFunction;
In the widget we listen for the table's                        break;
                                                         };
“delete” event and call the appropriate               };

handler object.                                       if(OS_IOS){
                                                         $.table.addEventListener('delete',
                                                      function(r){
                                                              handlers.deleteRow(r);	
                                                          });
                                                      };
THANK YOU

 Source code: http://bit.ly/alloy-customTableView

Slideshare: http://bit.ly/alloy-customTableViewSlides



             Mobile Data Systems Ltd.
            Turnkey mobile consultancy

            www.mobiledatasystems.co

      martin.hudson@mobiledatasystems.co

Creating Alloy Widgets

  • 1.
    ALLOY WIDGETS Improving codere-use through a library of bespoke UI components. TiConf.eu Martin Hudson, Jonti Hudson February 2013
  • 2.
    WHAT IS AWIDGET? A self-contained bespoke UI component that holds all the logic associated with its use.
  • 3.
    WHAT IS AWIDGET? A self-contained bespoke UI component that holds all the logic associated with its use. • Create a re-usable library across multiple projects
  • 4.
    WHAT IS AWIDGET? A self-contained bespoke UI component that holds all the logic associated with its use. • Create a re-usable library across multiple projects • Create components that manage cross- platform differences (e.g. a table edit / delete component)
  • 5.
    WHAT IS AWIDGET? A self-contained bespoke UI component that holds all the logic associated with its use. • Create a re-usable library across multiple projects • Create components that manage cross- platform differences (e.g. a table edit / delete component) • Improve readability of code
  • 6.
    WHAT IS AWIDGET? A self-contained bespoke UI component that holds all the logic associated with its use. • Create a re-usable library across multiple projects • Create components that manage cross- platform differences (e.g. a table edit / delete component) • Improve readability of code • Improve reliability due to re-use of tested components.
  • 7.
    WHAT IS AWIDGET? App Widget Multiple widgets in the same window...
  • 8.
    WHAT IS AWIDGET? App Widget ... or multiple instances of the same widget
  • 9.
    A CUSTOM TABLEVIEW WIDGET An example of building a cross-platform widget that encapsulates common functionality but utilises platform specific behaviour.
  • 10.
    CREATING A WIDGET Tocreate a new widget, right click the project name in the Titanium Studio project view... and select New → Alloy Widget.
  • 11.
    CREATING A WIDGET Tocreate a new widget, right click the project name in the Titanium Studio project view... and select New → Alloy Widget. Use a “Reverse domain” naming convention to ensure widget names are not replicated when you share widgets with others.
  • 12.
    WIDGET FILE STRUCTURE Awidgets folder is created with Controllers, Styles and Views sub-directories. Note the absence of Models – this is because the main app should handle data storage
  • 13.
    USING A WIDGET Inthe main app, we will call the newly created widget using the “Require” tag. App – index.xml Widget – widget.xml <Alloy> <Alloy> <Window class="container"> <TableView id="table"></TableView> <Require type="widget" </Alloy> src="co.mobiledatasystems.customEditableTable" id="table1"> </Require> <Button id="btnEdit" title="Allow Editing" onClick="btnEdit_click_Event"> </Button> </Window> </Alloy>
  • 14.
    USING A WIDGET Inthe main app, we will call the newly created widget using the “Require” tag. App – index.xml Widget – widget.xml <Alloy> <Alloy> <Window class="container"> <TableView id="table"></TableView> <Require type="widget" </Alloy> src="co.mobiledatasystems.customEditableTable" id="table1"> </Require> <Button id="btnEdit" title="Allow Editing" onClick="btnEdit_click_Event"> </Button> </Window> </Alloy> Note we specify that we want a widget and reference the name of our new widget. Alloy knows where to find it.
  • 15.
    USING A WIDGET Inthe main app, we will call the newly created widget using the “Require” tag. App – index.xml Widget – widget.xml <Alloy> <Alloy> <Window class="container"> <TableView id="table"></TableView> <Require type="widget" </Alloy> src="co.mobiledatasystems.customEditableTable" id="table1"> </Require> <Button id="btnEdit" title="Allow Editing" onClick="btnEdit_click_Event"> </Button> </Window> </Alloy> In the widget, we specify the UI components we want to expose. In our case it is only a TableView.
  • 16.
    STYLING App – index.tss Widget – widget.tss ".container": { backgroundColor:"white" }, "#table1": { left: '10dp', right: '10dp', top: '20dp', bottom:'80dp' }, "#btnEdit": { bottom:'10dp', left:'20dp', right:'20dp', height:'45dp' } We have referenced our instance of the widget “table1” in index.xml
  • 17.
    STYLING App – index.tss Widget – widget.tss ".container": { backgroundColor:"white" }, "#table1": { left: '10dp', right: '10dp', top: '40dp', bottom:'80dp' }, "#btnEdit": { bottom:'10dp', left:'20dp', right:'20dp', height:'45dp' } Note, where possible, do all the styling of widget components in the main app. This ensures maximum re-usability across projects.
  • 18.
    CONTROLLERS - INITIALISE App – index.tss Widget – widget.js //copy the arguments passed in to the widget via. ".container": { the xml and tss parameters backgroundColor:"white" }, var _args = arguments[0] || {}; "#table1": { var editable = null; left: '10dp', right: '10dp', if(OS_ANDROID){ top: '40dp', editable = false; bottom:'80dp' }; }, //get each element set in the widget's xml or tss "#btnEdit": { parameters bottom:'10dp', left:'20dp', Ti.API.info(JSON.stringify(_args)); right:'20dp', height:'45dp' //iterate round all the parameters we have passed } in for (var key in _args) { if (_args.hasOwnProperty(key)) { In the widget's controller we can //checks key is a direct property of _args, not access all the parameters passed in somewhere down the object tree using the arguments[] array. if(OS_ANDROID){ switch (key){
  • 19.
    CONTROLLERS - INITIALISE App – index.tss Widget – widget.js //copy the arguments passed in to the widget via. ".container": { the xml and tss parameters backgroundColor:"white" }, var _args = arguments[0] || {}; "#table1": { var editable = null; left: '10dp', right: '10dp', if(OS_ANDROID){ top: '40dp', editable = false; bottom:'80dp' }; }, //get each element set in the widget's xml or tss "#btnEdit": { parameters bottom:'10dp', left:'20dp', Ti.API.info(JSON.stringify(_args)); right:'20dp', height:'45dp' //iterate round all the parameters we have passed } in for (var key in _args) { if (_args.hasOwnProperty(key)) { In the widget's controller we can //checks key is a direct property of _args, not access all the parameters passed in somewhere down the object tree using the arguments[] array. if(OS_ANDROID){ switch (key){
  • 20.
    CONTROLLERS - INITIALISE App – index.tss Widget – widget.js //iterate round all the parameters we have passed ".container": { in backgroundColor:"white" }, for (var key in _args) { "#table1": { if (_args.hasOwnProperty(key)) { left: '10dp', right: '10dp', //checks key is a direct property of _args, not top: '40dp', somewhere down the object tree bottom:'80dp' }, if(OS_ANDROID){ "#btnEdit": { switch (key){ bottom:'10dp', case 'editing': left:'20dp', editable = _args[key]; right:'20dp', break; height:'45dp' case 'moving': break; //android } doesn't recognise this property default: We can read each parameter passed in } $.table[key] = _args[key]; and process them appropriately. In our } else { $.table[key] = _args[key]; example “editable” and “moving” are }; }; iOS specific. We will set a local }; variable in the case of Android.
  • 21.
    CONTROLLERS - INITIALISE App – index.tss Widget – widget.js //iterate round all the parameters we have passed ".container": { in backgroundColor:"white" }, for (var key in _args) { "#table1": { if (_args.hasOwnProperty(key)) { left: '10dp', right: '10dp', //checks key is a direct property of _args, not top: '40dp', somewhere down the object tree bottom:'80dp' }, if(OS_ANDROID){ "#btnEdit": { switch (key){ bottom:'10dp', case 'editing': left:'20dp', editable = _args[key]; right:'20dp', break; height:'45dp' case 'moving': break; //android } doesn't recognise this property default: We can read each parameter passed in } $.table[key] = _args[key]; and process them appropriately. In our } else { $.table[key] = _args[key]; example “editable” and “moving” are }; }; iOS specific. We will set a local }; variable in the case of Android.
  • 22.
    CONTROLLERS – CALLINGFUNCTIONS App – index.js Widget – widget.js $.index.open(); //custom method we expose to set the table's data var editMode = false; exports.setData = function(rows /*Ti.UI.Row*/){ $.table.setData(rows); //create some data to put in the table }; var rows = []; for(var i=0;i<10;i++){ //custom method we expose to allow the table to rows.push(Ti.UI.createTableViewRow({title:'Row be editable number ' + i})); exports.editing = function(edit /*bool*/){ }; if(OS_IOS){ $.table1.setData(rows); //call the "setData" $.table.editing = edit; //allow row method we created in the widget editing on iPhone & iPad } else { //toggle the "editable" mode of the table editable = edit; function btnEdit_click_Event(){ }; if(editMode){ }; $.btnEdit.title = "Allow Editing"; editMode = false; } else { Using the commonJS framework, we $.btnEdit.title = "Cancel Editing"; editMode = true; can expose functions in the widget. In }; $.table1.editing(editMode); //call the our example we expose “setData” so "editing" method we created in the widget }; we can populate the table after the widget has created it.
  • 23.
    CONTROLLERS – CALLINGFUNCTIONS App – index.js Widget – widget.js $.index.open(); //custom method we expose to set the table's data var editMode = false; exports.setData = function(rows /*Ti.UI.Row*/){ $.table.setData(rows); //create some data to put in the table }; var rows = []; for(var i=0;i<10;i++){ //custom method we expose to allow the table to rows.push(Ti.UI.createTableViewRow({title:'Row be editable number ' + i})); exports.editing = function(edit /*bool*/){ }; if(OS_IOS){ $.table1.setData(rows); //call the "setData" $.table.editing = edit; //allow row method we created in the widget editing on iPhone & iPad } else { //toggle the "editable" mode of the table editable = edit; function btnEdit_click_Event(){ }; if(editMode){ }; $.btnEdit.title = "Allow Editing"; editMode = false; } else { Using the commonJS framework, we $.btnEdit.title = "Cancel Editing"; editMode = true; can expose functions in the widget. In }; $.table1.editing(editMode); //call the our example we expose “setData” so "editing" method we created in the widget }; we can populate the table after the widget has created it.
  • 24.
    CONTROLLERS – CALLINGFUNCTIONS App – index.js Widget – widget.js $.index.open(); //custom method we expose to set the table's data var editMode = false; exports.setData = function(rows /*Ti.UI.Row*/){ $.table.setData(rows); //create some data to put in the table }; var rows = []; for(var i=0;i<10;i++){ //custom method we expose to allow the table to rows.push(Ti.UI.createTableViewRow({title:'Row be editable number ' + i})); exports.editing = function(edit /*bool*/){ }; if(OS_IOS){ $.table1.setData(rows); //call the "setData" $.table.editing = edit; //allow row method we created in the widget editing on iPhone & iPad } else { //toggle the "editable" mode of the table editable = edit; function btnEdit_click_Event(){ }; if(editMode){ }; $.btnEdit.title = "Allow Editing"; editMode = false; } else { $.btnEdit.title = "Cancel Editing"; editMode = true; Here, the main app is responding to a }; $.table1.editing(editMode); //call the button click event and changing the "editing" method we created in the widget }; editable state in the widget.
  • 25.
    CONTROLLERS – CALLINGFUNCTIONS App – index.js Widget – widget.js $.index.open(); //custom method we expose to set the table's data var editMode = false; exports.setData = function(rows /*Ti.UI.Row*/){ $.table.setData(rows); //create some data to put in the table }; var rows = []; for(var i=0;i<10;i++){ //custom method we expose to allow the table to rows.push(Ti.UI.createTableViewRow({title:'Row be editable number ' + i})); exports.editing = function(edit /*bool*/){ }; if(OS_IOS){ $.table1.setData(rows); //call the "setData" $.table.editing = edit; //allow row method we created in the widget editing on iPhone & iPad } else { //toggle the "editable" mode of the table editable = edit; function btnEdit_click_Event(){ }; if(editMode){ }; $.btnEdit.title = "Allow Editing"; editMode = false; } else { $.btnEdit.title = "Cancel Editing"; editMode = true; Here, the main app is responding to a }; $.table1.editing(editMode); //call the button click event and changing the "editing" method we created in the widget }; editable state in the widget.
  • 26.
    CONTROLLERS – HANDLINGEVENTS App – index.js Widget – widget.js $.table1.addEventListener('delete', function(r){ //create a handlers object that will contain Ti.API.info('row deleted: ' + JSON.stringify(r)); references to functions var dialog = Ti.UI.createAlertDialog({ var handlers = {}; message: r.row.title, title: 'Deleted' //assign some functions that do nothing. }); handlers.click = function(r){}; dialog.show(); handlers.deleteRow = function(r){}; }); //expose a function that can pass in a reference to an external function and assign the reference In the widget we create an to the appropriate handler. “addEventListener” function that has exports.addEventListener = function(listenerName, listenerFunction){ two parameters, the name of the event switch (listenerName){ case 'click' : and a reference to the function it will handlers.click = listenerFunction; break; call in the main app. case 'delete' : handlers.deleteRow = listenerFunction; break; We assign the reference to a }; }; “handlers” object we created in the if(OS_IOS){ widget. $.table.addEventListener('delete', function(r){
  • 27.
    CONTROLLERS – HANDLINGEVENTS App – index.js Widget – widget.js $.table1.addEventListener('delete', function(r){ //create a handlers object that will contain Ti.API.info('row deleted: ' + JSON.stringify(r)); references to functions var dialog = Ti.UI.createAlertDialog({ var handlers = {}; message: r.row.title, title: 'Deleted' //assign some functions that do nothing. }); handlers.click = function(r){}; dialog.show(); handlers.deleteRow = function(r){}; }); //expose a function that can pass in a reference to an external function and assign the reference to the appropriate handler. exports.addEventListener = function(listenerName, listenerFunction){ switch (listenerName){ In the main app we call the case 'click' : “addEventListener” function, passing in handlers.click = listenerFunction; break; the name of the listener and defining case 'delete' : handlers.deleteRow = listenerFunction; the function we want to execute when break; }; the even is fired. }; if(OS_IOS){ $.table.addEventListener('delete', function(r){
  • 28.
    CONTROLLERS – HANDLINGEVENTS App – index.js Widget – widget.js $.table1.addEventListener('delete', function(r){ //assign some functions that do nothing. Ti.API.info('row deleted: ' + JSON.stringify(r)); handlers.click = function(r){}; var dialog = Ti.UI.createAlertDialog({ handlers.deleteRow = function(r){}; message: r.row.title, title: 'Deleted' //expose a function that can pass in a reference }); to an external function and assign the reference dialog.show(); to the appropriate handler. }); exports.addEventListener = function(listenerName, listenerFunction){ switch (listenerName){ case 'click' : handlers.click = listenerFunction; break; case 'delete' : handlers.deleteRow = listenerFunction; In the widget we listen for the table's break; }; “delete” event and call the appropriate }; handler object. if(OS_IOS){ $.table.addEventListener('delete', function(r){ handlers.deleteRow(r); }); };
  • 29.
    THANK YOU Sourcecode: http://bit.ly/alloy-customTableView Slideshare: http://bit.ly/alloy-customTableViewSlides Mobile Data Systems Ltd. Turnkey mobile consultancy www.mobiledatasystems.co martin.hudson@mobiledatasystems.co