You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by ca...@apache.org on 2020/01/30 10:19:03 UTC

[royale-asjs] branch develop updated: todomvc-jewel-example: refactor to separate pieces and make it more "mvc"

This is an automated email from the ASF dual-hosted git repository.

carlosrovira pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git


The following commit(s) were added to refs/heads/develop by this push:
     new e67f344  todomvc-jewel-example: refactor to separate pieces and make it more "mvc"
e67f344 is described below

commit e67f3449023540d2ea7d471ce54b763e8269792b
Author: Carlos Rovira <ca...@apache.org>
AuthorDate: Thu Jan 30 11:18:40 2020 +0100

    todomvc-jewel-example: refactor to separate pieces and make it more "mvc"
---
 .../todomvc/src/main/resources/todomvc-styles.css  |  21 +-
 examples/jewel/todomvc/src/main/royale/App.mxml    |   3 +-
 .../jewel/todomvc/controllers/TodoController.as    | 177 +++++++++++++++++
 .../main/royale/jewel/todomvc/events/TodoEvent.as  |  68 +++++++
 .../main/royale/jewel/todomvc/models/TodoModel.as  | 134 +++++++++++++
 .../jewel/todomvc/renderers/TodoItemRenderer.mxml  |  92 +++++----
 .../royale/jewel/todomvc/views/MainContent.mxml    | 218 ---------------------
 .../royale/jewel/todomvc/views/TodoFooter.mxml     |  99 ++++++++++
 .../royale/jewel/todomvc/views/TodoHeader.mxml     |  74 +++++++
 .../jewel/todomvc/views/TodoListSection.mxml       |  87 ++++++++
 10 files changed, 711 insertions(+), 262 deletions(-)

diff --git a/examples/jewel/todomvc/src/main/resources/todomvc-styles.css b/examples/jewel/todomvc/src/main/resources/todomvc-styles.css
index 4b27e31..24264b3 100644
--- a/examples/jewel/todomvc/src/main/resources/todomvc-styles.css
+++ b/examples/jewel/todomvc/src/main/resources/todomvc-styles.css
@@ -21,6 +21,15 @@
 
 @namespace "http://www.w3.org/1999/xhtml";
 @namespace j "library://ns.apache.org/royale/jewel";
+@namespace todomvc "jewel.todomvc.views.*";
+
+/* Add Controller and Model beads to TodoListSectionComponent */
+todomvc|TodoListSection
+{
+	IBeadController: ClassReference("jewel.todomvc.controllers.TodoController");
+	IBeadModel: ClassReference("jewel.todomvc.models.TodoModel");
+}
+
 
 /* Application */
 .jewel.application {
@@ -65,7 +74,7 @@
 	margin: 3px;
     padding: 3px 7px;
 	background: none;
-	border: none;
+	border: 1px solid transparent;
 	box-shadow: none;
 	border-radius: 0.25rem;
 	color: #808080;
@@ -75,15 +84,17 @@
 }
 .jewel.button:hover, .jewel.button:hover:focus {
 	background: none;
-	border: none;
+	border: 1px solid transparent;
+
+	text-decoration: underline;	
 }
 .jewel.button:active, .jewel.button:active:focus {
 	background: none;
-	border: none;
+	border: 1px solid transparent;
 	box-shadow: none;
 }
 .jewel.button:focus {
-	border: none;
+	border: 1px solid transparent;
 	box-shadow: none;
 }
 
@@ -105,7 +116,7 @@
 }
 .jewel.togglebutton:active, .jewel.togglebutton:active:focus {
 	background: none;
-	border: 1px solid rgba(175,47,47,.2);;
+	border: 1px solid rgba(175,47,47,.2);
 	box-shadow: none;
 }
 .jewel.togglebutton:focus {
diff --git a/examples/jewel/todomvc/src/main/royale/App.mxml b/examples/jewel/todomvc/src/main/royale/App.mxml
index 6e0b7ac..546447b 100644
--- a/examples/jewel/todomvc/src/main/royale/App.mxml
+++ b/examples/jewel/todomvc/src/main/royale/App.mxml
@@ -28,6 +28,7 @@
     </j:valuesImpl>
 
     <j:initialView>
-        <views:MainContent/>
+        <views:TodoListSection/>
      </j:initialView>
+     
 </j:Application>
diff --git a/examples/jewel/todomvc/src/main/royale/jewel/todomvc/controllers/TodoController.as b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/controllers/TodoController.as
new file mode 100644
index 0000000..62f05d7
--- /dev/null
+++ b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/controllers/TodoController.as
@@ -0,0 +1,177 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package jewel.todomvc.controllers
+{
+	import jewel.todomvc.events.TodoEvent;
+	import jewel.todomvc.models.TodoModel;
+	import jewel.todomvc.vos.TodoVO;
+
+	import org.apache.royale.core.IBeadController;
+	import org.apache.royale.core.IBeadModel;
+	import org.apache.royale.core.IStrand;
+	import org.apache.royale.events.IEventDispatcher;
+
+	[Bindable]
+    /**
+     * The Todo Controller holds all the global actions. The views dispatch events that bubbles and
+	 * this class register to these evens and updates the model, so views can update accordingly using
+	 * binding most of the times.
+     */
+	public class TodoController implements IBeadController
+	{
+        /**
+		 *  constructor.
+		 */
+        public function TodoController():void
+		{
+        }
+
+        private var _strand:IStrand;
+		/**
+		 *  @copy org.apache.royale.core.IBead#strand
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10.2
+		 *  @playerversion AIR 2.6
+		 *  @productversion Royale 0.9.7
+		 */
+		public function set strand(value:IStrand):void {
+			_strand = value;
+			IEventDispatcher(_strand).addEventListener(TodoEvent.ADD_TODO_ITEM, addTodoItem);            
+			IEventDispatcher(_strand).addEventListener(TodoEvent.MARK_ALL_COMPLETE, markAllComplete);            
+			IEventDispatcher(_strand).addEventListener(TodoEvent.REMOVE_COMPLETED, removeCompleted);            
+			IEventDispatcher(_strand).addEventListener(TodoEvent.REFRESH_LIST, refreshList);            
+			IEventDispatcher(_strand).addEventListener(TodoEvent.ITEM_STATE_CHANGED, itemStateChangedHandler);            
+			IEventDispatcher(_strand).addEventListener(TodoEvent.ITEM_LABEL_CHANGED, itemLabelChangedHandler);            
+			IEventDispatcher(_strand).addEventListener(TodoEvent.ITEM_REMOVED, itemRemovedHandler);            
+			
+        	model = _strand.getBeadByType(IBeadModel) as TodoModel;
+			model.listItems = model.allItems;
+        }
+
+		/**
+		 *  Common todo model
+		 */
+		private var model:TodoModel;
+		
+        /**
+         *  Add the todo item to the list and refresh the list state 
+         */
+        protected function addTodoItem(event:TodoEvent):void {
+            model.allItems.addItem(event.todo);
+            updateInterface();
+        }
+        
+		/**
+         *  Mark all todo items as completed and update items left and clear completed button visibility
+         */
+        protected function markAllComplete(event:TodoEvent):void {
+            var len:int = model.allItems.length
+			var item:TodoVO;
+			for(var i:int = 0; i < len; i++) {
+				item = TodoVO(model.allItems.getItemAt(i));
+				item.done = true;
+			}
+
+			updateInterface();
+        }
+
+		/**
+         *  Remove all completed todo items, update footer and toggle all button visibility
+         */
+        protected function removeCompleted(event:TodoEvent):void {
+			var l:uint = model.allItems.length;
+			var item:TodoVO;
+			while(l--) {
+				item = TodoVO(model.allItems.getItemAt(l));
+				if(item.done){
+					model.allItems.removeItem(item);
+				}
+			}
+
+			model.footerVisibility = model.allItems.length != 0 ? true : false;
+			model.toogleAllVisibility = model.allItems.length != 0 ? true : false;
+		}
+
+		/**
+         *  Refresh the todo list to the appropiate filter state (All, Active or Completed)
+         */
+        protected function refreshList(event:TodoEvent):void
+		{
+			model.filterState = event.label;
+			setListState();
+		}
+
+		/**
+		 *  Sets the new state filter and refresh list to match the filter
+		 */
+        protected function setListState():void {
+			// setting to the same collection must cause refreshed too
+			model.listItems = null;
+
+			model.activeItems.refresh();
+			model.completedItems.refresh();
+
+			if(model.filterState == TodoModel.ALL_FILTER) {
+				model.listItems = model.allItems;
+			} 
+			else if(model.filterState == TodoModel.ACTIVE_FILTER) {
+				model.listItems = model.activeItems;
+			}
+			else if(model.filterState == TodoModel.COMPLETED_FILTER) {
+				model.listItems = model.completedItems;
+			}
+		}
+
+		/**
+		 *  When some todo item change state (done/undone), we must update the interface accordingly
+		 */
+        public function itemStateChangedHandler(event:TodoEvent = null):void {
+			event.todo.done = event.completion;
+			updateInterface();
+		}
+
+		/**
+		 *  Commit the label changes to the item
+		 */
+        public function itemLabelChangedHandler(event:TodoEvent = null):void {
+			event.todo.label = event.label;
+		}
+
+		/**
+		 *  When the user click in the renderer destroy button we must remove the item and update the interface
+		 */
+        public function itemRemovedHandler(event:TodoEvent):void {
+			model.allItems.removeItem(event.todo);
+            updateInterface();
+		}
+
+		/**
+		 *  Update the interface accordingly
+		 */
+		public function updateInterface():void {
+			setListState();
+
+			model.itemsLeftLabel = model.activeItems.length + " item left";
+            model.clearCompletedVisibility = model.completedItems.length != 0 ? true : false;
+			model.footerVisibility = model.allItems.length != 0 ? true : false;
+			model.toogleAllVisibility = model.allItems.length != 0 ? true : false;
+        }
+	}
+}
diff --git a/examples/jewel/todomvc/src/main/royale/jewel/todomvc/events/TodoEvent.as b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/events/TodoEvent.as
new file mode 100644
index 0000000..bdb2517
--- /dev/null
+++ b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/events/TodoEvent.as
@@ -0,0 +1,68 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package jewel.todomvc.events
+{
+	import jewel.todomvc.vos.TodoVO;
+
+	import org.apache.royale.events.Event;
+
+	/**
+	 * Todo Event
+	 */
+	public class TodoEvent extends Event
+	{
+		/**
+		 * Actions
+		 */
+		public static const ADD_TODO_ITEM:String = "add_Todo_Item";
+		public static const MARK_ALL_COMPLETE:String = "mark_all_complete";
+		public static const REMOVE_COMPLETED:String = "remove_completed";
+		public static const REFRESH_LIST:String = "refresh_list";
+
+		public static const ITEM_STATE_CHANGED:String = "item_state_changed";
+		public static const ITEM_LABEL_CHANGED:String = "item_label_changed";
+		public static const ITEM_REMOVED:String = "item_removed";
+
+		/**
+		 * The todo to pass between layers
+		 */
+		public var todo:TodoVO;
+		
+		/**
+		 * Use to send the filter state label or the changes in a todo item label
+		 */
+		public var label:String;
+		
+		/**
+		 * To send the state of the item (done/undone)
+		 */
+		public var completion:Boolean;
+
+        /**
+         * constructor
+         */
+		public function TodoEvent(type:String, todo:TodoVO = null, label:String = null, completion:Boolean = false) {
+			super(type, true);
+
+			this.todo = todo;
+			this.label = label;
+			this.completion = completion
+		}
+	}
+}
\ No newline at end of file
diff --git a/examples/jewel/todomvc/src/main/royale/jewel/todomvc/models/TodoModel.as b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/models/TodoModel.as
new file mode 100644
index 0000000..22dcdc5
--- /dev/null
+++ b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/models/TodoModel.as
@@ -0,0 +1,134 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package jewel.todomvc.models
+{
+	import jewel.todomvc.vos.TodoVO;
+
+	import org.apache.royale.collections.ArrayList;
+	import org.apache.royale.collections.ArrayListView;
+	import org.apache.royale.core.IBeadModel;
+	import org.apache.royale.core.IStrand;
+	import org.apache.royale.events.EventDispatcher;
+
+	[Bindable]
+    /**
+     *  Todo Model stores global model variables that are updated by controller
+     *  and used in views to update visuals for the user
+     */
+	public class TodoModel extends EventDispatcher implements IBeadModel
+	{
+        /**
+         * We have three todo list states: All, Active and Completed
+         */
+        public static const ALL_FILTER:String = "All";
+        public static const ACTIVE_FILTER:String = "Active";
+        public static const COMPLETED_FILTER:String = "Completed";
+
+        /**
+		 *  constructor.
+		 */
+        public function TodoModel():void
+        {
+            activeItems = filterItems(isActive);
+            completedItems = filterItems(isCompleted);
+        }
+        
+        private var _strand:IStrand;
+		/**
+		 *  @copy org.apache.royale.core.IBead#strand
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10.2
+		 *  @playerversion AIR 2.6
+		 *  @productversion Royale 0.9.7
+		 */
+		public function set strand(value:IStrand):void {
+        	_strand = value;
+        }
+
+        /**
+         * the list of items binded to the todo list component
+         */
+        public var listItems:Object;
+        
+        /**
+         * the real list with all items
+         */
+        public var allItems:ArrayList = new ArrayList();
+
+        /**
+         * the filtered list with active items
+         */
+        public var activeItems:ArrayListView;
+        
+        /**
+         * the filtered list with completed items
+         */
+        public var completedItems:ArrayListView;
+
+        /**
+         *  Filter the items in the list creating an ArrayListView with the right filter function
+         */
+        public function filterItems(filterFunction:Function = null):ArrayListView {
+            var alv:ArrayListView = new ArrayListView(allItems);
+            alv.filterFunction = filterFunction;
+            alv.refresh();
+            return alv;
+        }
+
+        /**
+         * filterFunction for the ArrayListView to get active items
+         */
+        public function isActive(item:TodoVO):Boolean {
+            return item && item.done == false;
+        }
+
+        /**
+         * filterFunction for the ArrayListView to get completed items
+         */
+        public function isCompleted(item:TodoVO):Boolean {
+            return item && item.done == true;
+        }
+
+        /**
+         * Stores the current filter for the list
+         */
+        public var filterState:String = TodoModel.ALL_FILTER;
+
+        /**
+         * how many items left to do
+         */
+        public var itemsLeftLabel:String = "0 items left";
+        
+        /**
+         * footer bar visibility
+         */
+        public var footerVisibility:Boolean = false;
+
+        /**
+         * toggle all button visibility
+         */
+        public var toogleAllVisibility:Boolean = false;
+
+        /**
+         * clear completed button visibility
+         */
+        public var clearCompletedVisibility:Boolean = false;
+	}
+}
diff --git a/examples/jewel/todomvc/src/main/royale/jewel/todomvc/renderers/TodoItemRenderer.mxml b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/renderers/TodoItemRenderer.mxml
index 3365ea3..55284af 100644
--- a/examples/jewel/todomvc/src/main/royale/jewel/todomvc/renderers/TodoItemRenderer.mxml
+++ b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/renderers/TodoItemRenderer.mxml
@@ -20,70 +20,86 @@ limitations under the License.
 <j:ListItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
     xmlns:j="library://ns.apache.org/royale/jewel" 
     xmlns:js="library://ns.apache.org/royale/basic"
-    width="100%" hoverable="false" selectable="false"
+    hoverable="false" selectable="false" width="100%"
     rollOver="rollOverHandler(event)"
     rollOut="rollOutHandler(event)">
 
     <fx:Script>
         <![CDATA[
+			import jewel.todomvc.events.TodoEvent;
 			import jewel.todomvc.vos.TodoVO;
 
 			import org.apache.royale.events.Event;
 			import org.apache.royale.events.MouseEvent;
-			import org.apache.royale.jewel.List;
-			import org.apache.royale.jewel.beads.views.ListView;
-
-            public var host:List;
-
+            
+            /**
+             *  Used to know if mouse is over this render in order to
+             *  show destroy button when exit editing state
+             */
+            private var mouseIsOverRenderer:Boolean = false;
+
+            /**
+             * the item used in bindnigs for this renderer
+             */
             [Bindable("dataChange")]
             public function get item():TodoVO {
                 return data as TodoVO;
             }
 
-            override public function set data(value:Object):void
-            {
-                if (value != data)
-                {
-                    super.data = value;
-                    dispatchEvent(new Event("dataChange"));
-                    trace(description)
-                }
+            /**
+             *  Change the item state between done/undone
+             */
+            public function changeItemState(event:Event):void {
+                dispatchEvent(new TodoEvent(TodoEvent.ITEM_STATE_CHANGED, item, null, event.target.selected));
             }
 
-            public function clickCloseButton(event:MouseEvent):void {
-                var view:ListView = itemRendererParent as ListView;
-				host = view.host as List;
-                dispatchEvent(new Event("removeItem", true));
+            /**
+             *  Destroy this todo item
+             */
+            public function removeItemClickHandler(event:MouseEvent):void {
+                dispatchEvent(new TodoEvent(TodoEvent.ITEM_REMOVED, item));
             }
 
-            public function edit(event:Event):void {
-                item.label = event.target.text;
+            /**
+             *  If user made changes to label, commit changes to the todo item and exit 'editing' state
+             */
+            public function updateLabelAndExit(event:Event):void {
+                if(item.label != event.target.text)
+                    dispatchEvent(new TodoEvent(TodoEvent.ITEM_LABEL_CHANGED, item, event.target.text));
                 currentState = 'normal';
+                if(mouseIsOverRenderer)
+                    destroy_btn.visible = true;
             }
 
-            public function changeItemState(event:Event):void {
-                item.done = event.target.selected;
-                dispatchEvent(new Event("itemStateChanged", true));
-            }
-
+            /**
+             *  Change renderer state to edit mode by double clicking in the todo item label
+             */
             public function goToEditMode(event:MouseEvent):void
             {
                 editfield.text = description.text;
                 currentState = "editing";
-                closeBtn.visible = false;
+                destroy_btn.visible = false;
                 editfield.setFocus();
             }
 
-            public function rollOverHandler(event:Event):void
+            /**
+             *  Show destroy button when user rolls over the renderer
+             */
+            public function rollOverHandler(event:MouseEvent):void
             {
+                mouseIsOverRenderer = true;
                 if(currentState == "normal")
-                    closeBtn.visible = true;
+                    destroy_btn.visible = true;
             }
             
-            public function rollOutHandler(event:Event):void
+            /**
+             *  Hide destroy button when user rolls out the renderer
+             */
+            public function rollOutHandler(event:MouseEvent):void
             {
+                mouseIsOverRenderer = false;
                 if(currentState == "normal")
-                    closeBtn.visible = false;
+                    destroy_btn.visible = false;
             }
 		]]>
     </fx:Script>
@@ -98,22 +114,22 @@ limitations under the License.
         <js:ItemRendererDataBinding />
     </j:beads>
     
-    <j:CheckBox
-        selected="{item ? (item.done ? true : false) : false }"
-        click="changeItemState(event);"
-        visible.normal="true" visible.editing="false"/>
+    <j:CheckBox selected="{item ? (item.done ? true : false) : false }"
+        visible.normal="true" visible.editing="false"
+        click="changeItemState(event);"/>
     
     <j:Label localId="description" width="100%" 
         text="{item ? item.label : ''}" multiline="true"
-        doubleClick="goToEditMode(event)" 
         visible.normal="true" visible.editing="false"
-        className="{item ? (item.done ? 'todolabel completed' : 'todolabel') : 'todolabel' }"/>
+        className="{item ? (item.done ? 'todolabel completed' : 'todolabel') : 'todolabel' }"
+        doubleClick="goToEditMode(event)"/>
 
     <j:TextInput localId="editfield" width="100%"
         visible.normal="false" visible.editing="true"
-        enter="edit(event)"/>
+        enter="updateLabelAndExit(event)"/>
 
-    <j:IconButton localId="closeBtn" click="clickCloseButton(event)" visible="false" className="destroy">
+    <j:IconButton localId="destroy_btn" visible="false" className="destroy"
+        click="removeItemClickHandler(event)">
         <j:icon>
             <js:FontIcon text="{MaterialIconType.CLOSE}" material="true"/>
         </j:icon>
diff --git a/examples/jewel/todomvc/src/main/royale/jewel/todomvc/views/MainContent.mxml b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/views/MainContent.mxml
deleted file mode 100644
index b5c4c6c..0000000
--- a/examples/jewel/todomvc/src/main/royale/jewel/todomvc/views/MainContent.mxml
+++ /dev/null
@@ -1,218 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
--->
-<j:View xmlns:fx="http://ns.adobe.com/mxml/2009"
-    xmlns:j="library://ns.apache.org/royale/jewel"
-    xmlns:js="library://ns.apache.org/royale/basic"
-    xmlns:html="library://ns.apache.org/royale/html"
-    initComplete="setUp()">
-
-    <fx:Script>
-		<![CDATA[
-        import jewel.todomvc.vos.TodoVO;
-
-        import org.apache.royale.collections.ArrayList;
-        import org.apache.royale.collections.ArrayListView;
-        import org.apache.royale.events.Event;
-
-        [Bindable]
-        public var items:ArrayList = new ArrayList();
-
-        [Bindable]
-        public var completedItems:ArrayListView;
-        
-        [Bindable]
-        public var activeItems:ArrayListView;
-
-        public function setUp():void {
-            todolist.addEventListener("itemStateChanged", itemStateChangedHandler);
-            todolist.addEventListener("removeItem", removeItemHandler);
-
-            activeItems = itemsCompleted(items, isActive);
-            completedItems = itemsCompleted(items, isCompleted);
-        }
-
-        private function addItem(event:Event):void {
-            if(event.target.text == "") return; 
-            var newItem:TodoVO = new TodoVO(event.target.text);
-            items.addItem(newItem);
-            event.target.text = "";
-            itemStateChangedHandler();
-        }
-        
-        public function itemsCompleted(listOfItems:ArrayList, filterFunction:Function = null):ArrayListView {
-            var alv:ArrayListView = new ArrayListView(listOfItems);
-            alv.filterFunction = filterFunction;
-            alv.refresh();
-            return alv;
-        }
-
-        public function allItems(item:TodoVO):Boolean {
-            return true;
-        }
-
-        public function isActive(item:TodoVO):Boolean {
-            return item && item.done == false;
-        }
-
-        public function isCompleted(item:TodoVO):Boolean {
-            return item && item.done == true;
-        }
-        
-        //Mark all as complete
-        public function markAllAsComplete():void {
-            var len:int = items.length
-            var item:TodoVO;
-            for(var i:int = 0; i < len; i++)
-            {
-                item = TodoVO(items.getItemAt(i));
-                item.done = true;
-            }
-        }
-
-        public function removeCompleted():void {
-            var l:uint = items.length;
-            var item:TodoVO;
-            while(l--) {
-                item = TodoVO(items.getItemAt(l));
-                if(item.done){
-                    items.removeItem(item);
-                }
-            }
-            clearCompleted.visible = false;
-            toogleAll.visible = footer.visible = itemsCompleted(items, null).length != 0 ? true : false;
-            
-            if(all_btn.selected)
-                selectFilter(all_btn.text);
-            else if(active_btn.selected)
-                selectFilter(active_btn.text);
-            else if(completed_btn.selected)
-                selectFilter(completed_btn.text);
-        }
-
-        public function itemStateChangedHandler(event:Event = null):void {
-            itemsLeft.text = itemsCompleted(items, isActive).length + " item left";
-            clearCompleted.visible = itemsCompleted(items, isCompleted).length != 0 ? true : false;
-            toogleAll.visible = footer.visible = itemsCompleted(items, null).length != 0 ? true : false;
-        }
-        
-        public function removeItemHandler(event:Event):void {
-            items.removeItem(event.target.data);
-            itemStateChangedHandler();
-        }
-        
-        public function toggleButtonClickHandler(event:Event):void {
-            selectFilter(event.target.text);
-        }
-        public function selectFilter(label:String):void {
-            if(label == "All")
-            {
-                active_btn.selected = false;
-                completed_btn.selected = false;
-
-                todolist.dataProvider = items;
-            } 
-            else if(label == "Active")
-            {
-                all_btn.selected = false;
-                completed_btn.selected = false;
-
-                activeItems.refresh();
-
-                todolist.dataProvider = activeItems;
-            }
-            else if(label == "Completed")
-            {
-                all_btn.selected = false;
-                active_btn.selected = false;
-
-                completedItems.refresh();
-
-                todolist.dataProvider = completedItems;
-            }
-        }
-        ]]>
-	</fx:Script>
- 
-    <j:beads>
-        <js:ContainerDataBinding/>
-    </j:beads>
-
-    <html:Section className="todoapp">
-        <html:H1 text="todos"/>
-
-        <html:Header localId="header">
-            <j:Group>
-                <j:TextInput localId="need" enter="addItem(event)" width="100%" className="new-todo">
-                    <j:beads>
-                        <j:TextPrompt prompt="What needs to be done?"/>
-                    </j:beads>
-                </j:TextInput>
-                <j:IconButton localId="toogleAll" click="markAllAsComplete()" visible="false"
-                    width="40" x="10" y="10" className="toggle-all">
-                    <j:icon>
-                        <js:FontIcon text="{MaterialIconType.KEYBOARD_ARROW_DOWN}" material="true"/>
-                    </j:icon>
-                </j:IconButton>
-            </j:Group>
-        </html:Header>
-
-        <html:Section localId="main">
-            <j:List localId="todolist" width="100%" rowHeight="55"
-                labelField="label" className="todo-list"
-                initComplete="todolist.dataProvider = itemsCompleted(items, null)">
-                <j:beads>
-                    <j:AddListItemRendererForArrayListData/>
-                    <j:RemoveListItemRendererForArrayListData/>
-                    <j:UpdateListItemRendererForArrayListData/>
-                </j:beads>
-            </j:List>
-        </html:Section>
-
-        <html:Footer localId="footer" className="footer" visible="false">
-            <j:BarRow>
-                <j:BarSection width="15%">
-                    <j:Label localId="itemsLeft" text="0 items left"/>
-                </j:BarSection>
-                <j:BarSection gap="3" itemsHorizontalAlign="itemsCenter">
-                    <j:ToggleButton localId="all_btn" text="All" click="toggleButtonClickHandler(event)" selected="true"/>
-                    <j:ToggleButton localId="active_btn" text="Active" click="toggleButtonClickHandler(event)"/>
-                    <j:ToggleButton localId="completed_btn" text="Completed" click="toggleButtonClickHandler(event)"/>
-                </j:BarSection>
-                <j:BarSection width="15%" itemsHorizontalAlign="itemsRight">
-                    <j:Button localId="clearCompleted" text="Clear Completed" click="removeCompleted()" visible="false"/>
-                </j:BarSection>
-            </j:BarRow>
-
-        </html:Footer>
-    </html:Section>
-    
-    <html:Footer className="info">
-        <![CDATA[
-            <p>Double-click to edit a todo</p>
-            <p>
-                Created by
-                <a href="http://github.com/carlosrovira" target="_blank">Carlos Rovira</a>
-                for
-                <a href="http://royale.apache.org" target="_blank">Apache Royale</a>
-            </p>
-            <p>Inspired in <a href="http://todomvc.com" target="_blank">TodoMVC</a></p>
-        ]]>
-    </html:Footer>
-</j:View>
\ No newline at end of file
diff --git a/examples/jewel/todomvc/src/main/royale/jewel/todomvc/views/TodoFooter.mxml b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/views/TodoFooter.mxml
new file mode 100644
index 0000000..0c76f78
--- /dev/null
+++ b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/views/TodoFooter.mxml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-->
+<j:BarRow xmlns:fx="http://ns.adobe.com/mxml/2009"
+	xmlns:j="library://ns.apache.org/royale/jewel"
+	xmlns:js="library://ns.apache.org/royale/basic">
+
+    <fx:Script>
+        <![CDATA[
+            import jewel.todomvc.models.TodoModel;
+            import jewel.todomvc.events.TodoEvent;
+
+            [Bindable]
+            public var todoModel:TodoModel;
+
+            /**
+             *  All toggle buttons runs select filter
+             */
+            public function toggleButtonClickHandler(event:Event):void {
+                selectFilter(event.target.text);
+            }
+
+            /**
+             *  Update buttons states and refresh the list updating the list model
+             */
+            public function selectFilter(label:String):void {
+                if(label == TodoModel.ALL_FILTER)
+                {
+                    active_btn.selected = false;
+                    completed_btn.selected = false;
+                } 
+                else if(label == TodoModel.ACTIVE_FILTER)
+                {
+                    all_btn.selected = false;
+                    completed_btn.selected = false;
+
+                }
+                else if(label == TodoModel.COMPLETED_FILTER)
+                {
+                    all_btn.selected = false;
+                    active_btn.selected = false;
+                }
+
+                dispatchEvent(new TodoEvent(TodoEvent.REFRESH_LIST, null, label));
+            }
+
+            /**
+             *  Remove all completed todo items and update the todo list with the right filter
+             */
+            public function removeCompleted():void {
+                dispatchEvent(new TodoEvent(TodoEvent.REMOVE_COMPLETED));
+
+                clearCompleted.visible = false;
+                
+                if(all_btn.selected)
+                    selectFilter(all_btn.text);
+                else if(active_btn.selected)
+                    selectFilter(active_btn.text);
+                else if(completed_btn.selected)
+                    selectFilter(completed_btn.text);
+            }
+        ]]>
+    </fx:Script>
+
+    <j:beads>
+        <js:ContainerDataBinding/>
+    </j:beads>
+
+    <j:BarSection width="15%">
+        <j:Label localId="itemsLeft" text="{todoModel.itemsLeftLabel}"/>
+    </j:BarSection>
+
+    <j:BarSection gap="3" itemsHorizontalAlign="itemsCenter">
+        <j:ToggleButton localId="all_btn" text="All" click="toggleButtonClickHandler(event)" selected="true"/>
+        <j:ToggleButton localId="active_btn" text="Active" click="toggleButtonClickHandler(event)"/>
+        <j:ToggleButton localId="completed_btn" text="Completed" click="toggleButtonClickHandler(event)"/>
+    </j:BarSection>
+
+    <j:BarSection width="15%" gap="3" itemsHorizontalAlign="itemsRight">
+        <j:Button localId="clearCompleted" text="Clear Completed" click="removeCompleted()" visible="{todoModel.clearCompletedVisibility}"/>
+    </j:BarSection>
+
+</j:BarRow>
\ No newline at end of file
diff --git a/examples/jewel/todomvc/src/main/royale/jewel/todomvc/views/TodoHeader.mxml b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/views/TodoHeader.mxml
new file mode 100644
index 0000000..3487343
--- /dev/null
+++ b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/views/TodoHeader.mxml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-->
+<j:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
+	xmlns:j="library://ns.apache.org/royale/jewel"
+	xmlns:js="library://ns.apache.org/royale/basic">
+
+	<fx:Script>
+		<![CDATA[
+			import jewel.todomvc.events.TodoEvent;
+			import jewel.todomvc.models.TodoModel;
+			import jewel.todomvc.vos.TodoVO;
+
+			import org.apache.royale.events.Event;
+
+			[Bindable]
+			public var todoModel:TodoModel;
+
+			/**
+			 *  Signal todo item addition from main text box
+			 */
+			private function addItem(event:Event):void {
+				if(event.target.text == "") return; 
+				var newTodo:TodoVO = new TodoVO(event.target.text);
+				event.target.text = "";
+				
+				dispatchEvent(new TodoEvent(TodoEvent.ADD_TODO_ITEM, newTodo));
+			}
+
+			/**
+			 *  Mark all todo items complete
+			 */ 
+			public function markAllComplete(event:Event):void {
+				dispatchEvent(new TodoEvent(TodoEvent.MARK_ALL_COMPLETE));
+			}
+		]]>
+	</fx:Script>
+
+	<j:beads>
+        <js:ContainerDataBinding/>
+    </j:beads>
+
+	<j:TextInput localId="need" width="100%" className="new-todo" 
+		enter="addItem(event)">
+		<j:beads>
+			<j:TextPrompt prompt="What needs to be done?"/>
+		</j:beads>
+	</j:TextInput>
+
+	<j:IconButton localId="toogleAll" visible="{todoModel.toogleAllVisibility}"
+		width="40" x="10" y="10" className="toggle-all"
+		click="markAllComplete(event)">
+		<j:icon>
+			<js:FontIcon text="{MaterialIconType.KEYBOARD_ARROW_DOWN}" material="true"/>
+		</j:icon>
+	</j:IconButton>
+
+</j:Group>
\ No newline at end of file
diff --git a/examples/jewel/todomvc/src/main/royale/jewel/todomvc/views/TodoListSection.mxml b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/views/TodoListSection.mxml
new file mode 100644
index 0000000..d0b50f4
--- /dev/null
+++ b/examples/jewel/todomvc/src/main/royale/jewel/todomvc/views/TodoListSection.mxml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-->
+<j:View xmlns:fx="http://ns.adobe.com/mxml/2009"
+    xmlns:j="library://ns.apache.org/royale/jewel"
+    xmlns:js="library://ns.apache.org/royale/basic"
+    xmlns:html="library://ns.apache.org/royale/html"
+    xmlns:views="jewel.todomvc.views.*"
+    initComplete="setUp()">
+
+    <fx:Script>
+        <![CDATA[
+            import jewel.todomvc.models.TodoModel;
+            import org.apache.royale.core.IBeadModel;
+            
+            [Bindable]
+			public var todoModel:TodoModel;
+
+            /**
+             * setUp child views
+             */
+            public function setUp():void
+            {
+                todoModel = getBeadByType(IBeadModel) as TodoModel;
+                header.todoModel = todoModel;
+                footer.todoModel = todoModel;
+            }
+        ]]>
+    </fx:Script>
+
+    <j:beads>
+        <js:ContainerDataBinding/>
+    </j:beads>
+
+    <html:Section className="todoapp">
+        <html:H1 text="todos"/>
+        
+        <html:Header>
+            <views:TodoHeader localId="header"/>
+        </html:Header>
+        
+        <html:Section localId="main">
+            <j:List localId="todolist" width="100%" rowHeight="55"
+                labelField="label" className="todo-list" 
+                dataProvider="{todoModel.listItems}">
+                <j:beads>
+                    <j:AddListItemRendererForArrayListData/>
+                    <j:RemoveListItemRendererForArrayListData/>
+                    <j:UpdateListItemRendererForArrayListData/>
+                </j:beads>
+            </j:List>
+        </html:Section>
+        
+        <html:Footer className="footer" visible="{todoModel.footerVisibility}">
+            <views:TodoFooter localId="footer"/>
+        </html:Footer>
+    </html:Section>
+    
+    <html:Footer className="info">
+        <![CDATA[
+            <p>Double-click to edit a todo</p>
+            <p>
+                Created by
+                <a href="http://github.com/carlosrovira" target="_blank">Carlos Rovira</a>
+                for
+                <a href="http://royale.apache.org" target="_blank">Apache Royale</a>
+            </p>
+            <p>Inspired in <a href="http://todomvc.com" target="_blank">TodoMVC</a></p>
+        ]]>
+    </html:Footer>
+</j:View>
\ No newline at end of file