<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress/2.2" -->
<rss version="2.0" 
	xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
	<title>Comments on: New version of RemoteList (IList implementation that support paging)</title>
	<link>http://blog.widget-labs.com/2007/01/21/new-version-of-remotelist-ilist-implementation-that-support-paging/</link>
	<description></description>
	<pubDate>Sat, 31 Jul 2010 07:31:35 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.2</generator>

	<item>
		<title>By: Snehal</title>
		<link>http://blog.widget-labs.com/2007/01/21/new-version-of-remotelist-ilist-implementation-that-support-paging/#comment-1228</link>
		<author>Snehal</author>
		<pubDate>Fri, 21 Nov 2008 11:13:39 +0000</pubDate>
		<guid>http://blog.widget-labs.com/2007/01/21/new-version-of-remotelist-ilist-implementation-that-support-paging/#comment-1228</guid>
		<description>It seems whole code will not fit here so just adding needed methods.

Thanks for your postings. It seems reasonable solution. I have implemented sorting by converting RemoteList class to RemoteCollection (which extends ListCollectionView).

In RemoteCollection, I have added refresh method, which calls private method - internalRefresh, which does sorting and filtering work. Filtering is not yet implemented but it can be implemented similarly. In addition, RemoteDataSet should implement sort method and optionally server object could maintain cache of sorted data. So I have to pass one dataField instead of passing array of dataField to support multiple column sorting.

Source code of RemoteCollection:

public class RemoteCollection extends ListCollectionView
{
 
override public function refresh():Boolean {		
			return internalRefresh(true);;
		}

 private function internalRefresh(dispatch:Boolean):Boolean
	    {	
	    	    
	    	if(filterFunction &#124;&#124; sort)
	    	{
		    	pagesLoaded = new Array();
				pagesPending = new Array();
				   	
	            if (sort)
	            {
	                remoteDataSet.sort(sort);	
	                reloadLocalData = true;
	                localData = new Array();
	                localData.length = totalLength;	                
					dispatchResetEvent();         
	            }
	     	}
	     	    
	        return true;
	    } 
}

Problem: I am calling collection reset event after sorting is being done and it will reset the datagrid and show the first page.  This might be ok but according to my need it should  follow the same behavior as client side sorting. By default. it shows the page of selected item even after sorting.

Solution: I am still looking for appropriate solution. I have done some trial and error analysis and found that by calling super.refresh method of ListControlView from inherited class, it will page to selected item. But it is hard to get selectedItem until datagrid calls getSelectedItem method of this class. So it is straight forward to determine which page to load and display. I have made some workarounds and seems working but I am looking for stable and appropriate solution. Your help would be appriciated. I will contribute my progress as well.

CHEERS,
Sne</description>
		<content:encoded><![CDATA[<p>It seems whole code will not fit here so just adding needed methods.</p>
<p>Thanks for your postings. It seems reasonable solution. I have implemented sorting by converting RemoteList class to RemoteCollection (which extends ListCollectionView).</p>
<p>In RemoteCollection, I have added refresh method, which calls private method - internalRefresh, which does sorting and filtering work. Filtering is not yet implemented but it can be implemented similarly. In addition, RemoteDataSet should implement sort method and optionally server object could maintain cache of sorted data. So I have to pass one dataField instead of passing array of dataField to support multiple column sorting.</p>
<p>Source code of RemoteCollection:</p>
<p>public class RemoteCollection extends ListCollectionView<br />
{</p>
<p>override public function refresh():Boolean {<br />
			return internalRefresh(true);;<br />
		}</p>
<p> private function internalRefresh(dispatch:Boolean):Boolean<br />
	    {	</p>
<p>	    	if(filterFunction || sort)<br />
	    	{<br />
		    	pagesLoaded = new Array();<br />
				pagesPending = new Array();</p>
<p>	            if (sort)<br />
	            {<br />
	                remoteDataSet.sort(sort);<br />
	                reloadLocalData = true;<br />
	                localData = new Array();<br />
	                localData.length = totalLength;<br />
					dispatchResetEvent();<br />
	            }<br />
	     	}</p>
<p>	        return true;<br />
	    }<br />
}</p>
<p>Problem: I am calling collection reset event after sorting is being done and it will reset the datagrid and show the first page.  This might be ok but according to my need it should  follow the same behavior as client side sorting. By default. it shows the page of selected item even after sorting.</p>
<p>Solution: I am still looking for appropriate solution. I have done some trial and error analysis and found that by calling super.refresh method of ListControlView from inherited class, it will page to selected item. But it is hard to get selectedItem until datagrid calls getSelectedItem method of this class. So it is straight forward to determine which page to load and display. I have made some workarounds and seems working but I am looking for stable and appropriate solution. Your help would be appriciated. I will contribute my progress as well.</p>
<p>CHEERS,<br />
Sne</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Snehal</title>
		<link>http://blog.widget-labs.com/2007/01/21/new-version-of-remotelist-ilist-implementation-that-support-paging/#comment-1227</link>
		<author>Snehal</author>
		<pubDate>Fri, 21 Nov 2008 10:52:11 +0000</pubDate>
		<guid>http://blog.widget-labs.com/2007/01/21/new-version-of-remotelist-ilist-implementation-that-support-paging/#comment-1227</guid>
		<description>Thanks for your postings. It seems reasonable solution. I have implemented sorting by converting RemoteList class to RemoteCollection (which extends ListCollectionView).

In RemoteCollection, I have added refresh method, which calls private method - internalRefresh, which does sorting and filtering work. Filtering is not yet implemented but it can be implemented similarly. In addition, RemoteDataSet should implement sort method and optionally server object could maintain cache of sorted data. So I have to pass only one dataField instead of array of dataField in order to support multiple column sorting.  

Source code of RemoteCollection:

public class RemoteCollection extends ListCollectionView
	{
		/**
		 * Page size. Default = 100;
		 */ 
		public var  pageSize : int;	
		
		/**
		 * Specifies if loaded data should be cleaned when not used. Default is false.
		 */ 
		public var cleanData:Boolean = false;
		public var reloadLocalData:Boolean = false;
		
		private var remoteDataSet:IRemoteDataSet;		
		private var localData : Array;
		private var pagesLoaded : Array;
		private var pagesPending : Array;
		private var isDataInit:Boolean = false; 
		
		private var eventDispatcher:EventDispatcher;				
		private var totalLength:int;
		
		public function RemoteCollection(ds:IRemoteDataSet)
		{
			localData = new Array();
			pagesLoaded = new Array();
			pagesPending = new Array();
			pageSize = 100; 
			
			remoteDataSet = ds;
			ds.registerListeners("getRows", onDataReady, onError);
			ds.registerListeners("getLength", onLengthReady, onError);
			remoteDataSet.getLength();			
			
		}
		
		private function onLengthReady(result:Object):void 
		{
			totalLength = uint(result.result);
			localData.length = totalLength;
			
			//trace("onLengthReady:" + localData.length)			
			dispatchResetEvent();			
		}
		
		override public function get length():int
		{
			return localData.length;
		}

		override public function getItemAt(index:int, prefetch:int=0.0):Object
		{
			var item:Object = localData[index];
			if (item == null)
			{
				miss(index);
			}
			return item;
		}
		
		/**
		 * Called when we need to load a new page of data and throws a new exception for first request or 
		 * rethrows already created exception if data loading already in progress.
		 */ 
		public function miss(index:int):void
		{
			var item:Object = localData[index];
			if (item == null)
			{
				var page : Number = Math.floor(index / pageSize);
				
				if (pagesPending[page] == null)
				{
					remoteDataSet.loadData(page, pageSize);	
					
					var loadingEvent:Event = new Event("Loading");
					dispatchEvent(loadingEvent);			
					
					var error:ItemPendingErrorEx = new ItemPendingErrorEx("Loading Data ...");
					pagesPending[page] = error;
					throw error;
				} else 
				{
					throw pagesPending[page];
				}
			}
		}
		
		public function onDataReady(loadedData:Object):void
		{
			var result:Array = loadedData.result[0]["value"].toArray();			
			var page:int = loadedData.result[1]["value"];
			
			var error:ItemPendingErrorEx = pagesPending[page];
			
			pagesLoaded[page] = true;
			var beginIdx : Number = page * pageSize;

			localData.splice.apply(localData, [beginIdx, result.length].concat(result));
			
			if (cleanData) 
			{
				cleanInvisiblePages(page);
			}
			
			trace("localData is updated: " + beginIdx + "-" + (beginIdx + result.length) );            			
			
			error.dataReady(result);
			
			if (isDataInit == false) 
			{
				isDataInit = true;
				dispatchResetEvent(); // make columns are initialized
			}
			
			var dataReadyEvent:Event = new Event("DataReady");
			dispatchEvent(dataReadyEvent);
			
		}
		
		private function cleanInvisiblePages(page:int):void
		{
			trace("start cleaning");
			for (var k:int = 0; k  (page+1) &#124;&#124; k  length) ? length : end;
					
					for (var i:int = start; i </description>
		<content:encoded><![CDATA[<p>Thanks for your postings. It seems reasonable solution. I have implemented sorting by converting RemoteList class to RemoteCollection (which extends ListCollectionView).</p>
<p>In RemoteCollection, I have added refresh method, which calls private method - internalRefresh, which does sorting and filtering work. Filtering is not yet implemented but it can be implemented similarly. In addition, RemoteDataSet should implement sort method and optionally server object could maintain cache of sorted data. So I have to pass only one dataField instead of array of dataField in order to support multiple column sorting.  </p>
<p>Source code of RemoteCollection:</p>
<p>public class RemoteCollection extends ListCollectionView<br />
	{<br />
		/**<br />
		 * Page size. Default = 100;<br />
		 */<br />
		public var  pageSize : int;	</p>
<p>		/**<br />
		 * Specifies if loaded data should be cleaned when not used. Default is false.<br />
		 */<br />
		public var cleanData:Boolean = false;<br />
		public var reloadLocalData:Boolean = false;</p>
<p>		private var remoteDataSet:IRemoteDataSet;<br />
		private var localData : Array;<br />
		private var pagesLoaded : Array;<br />
		private var pagesPending : Array;<br />
		private var isDataInit:Boolean = false; </p>
<p>		private var eventDispatcher:EventDispatcher;<br />
		private var totalLength:int;</p>
<p>		public function RemoteCollection(ds:IRemoteDataSet)<br />
		{<br />
			localData = new Array();<br />
			pagesLoaded = new Array();<br />
			pagesPending = new Array();<br />
			pageSize = 100; </p>
<p>			remoteDataSet = ds;<br />
			ds.registerListeners(&#8221;getRows&#8221;, onDataReady, onError);<br />
			ds.registerListeners(&#8221;getLength&#8221;, onLengthReady, onError);<br />
			remoteDataSet.getLength();			</p>
<p>		}</p>
<p>		private function onLengthReady(result:Object):void<br />
		{<br />
			totalLength = uint(result.result);<br />
			localData.length = totalLength;</p>
<p>			//trace(&#8221;onLengthReady:&#8221; + localData.length)<br />
			dispatchResetEvent();<br />
		}</p>
<p>		override public function get length():int<br />
		{<br />
			return localData.length;<br />
		}</p>
<p>		override public function getItemAt(index:int, prefetch:int=0.0):Object<br />
		{<br />
			var item:Object = localData[index];<br />
			if (item == null)<br />
			{<br />
				miss(index);<br />
			}<br />
			return item;<br />
		}</p>
<p>		/**<br />
		 * Called when we need to load a new page of data and throws a new exception for first request or<br />
		 * rethrows already created exception if data loading already in progress.<br />
		 */<br />
		public function miss(index:int):void<br />
		{<br />
			var item:Object = localData[index];<br />
			if (item == null)<br />
			{<br />
				var page : Number = Math.floor(index / pageSize);</p>
<p>				if (pagesPending[page] == null)<br />
				{<br />
					remoteDataSet.loadData(page, pageSize);	</p>
<p>					var loadingEvent:Event = new Event(&#8221;Loading&#8221;);<br />
					dispatchEvent(loadingEvent);			</p>
<p>					var error:ItemPendingErrorEx = new ItemPendingErrorEx(&#8221;Loading Data &#8230;&#8221;);<br />
					pagesPending[page] = error;<br />
					throw error;<br />
				} else<br />
				{<br />
					throw pagesPending[page];<br />
				}<br />
			}<br />
		}</p>
<p>		public function onDataReady(loadedData:Object):void<br />
		{<br />
			var result:Array = loadedData.result[0][&#8221;value&#8221;].toArray();<br />
			var page:int = loadedData.result[1][&#8221;value&#8221;];</p>
<p>			var error:ItemPendingErrorEx = pagesPending[page];</p>
<p>			pagesLoaded[page] = true;<br />
			var beginIdx : Number = page * pageSize;</p>
<p>			localData.splice.apply(localData, [beginIdx, result.length].concat(result));</p>
<p>			if (cleanData)<br />
			{<br />
				cleanInvisiblePages(page);<br />
			}</p>
<p>			trace(&#8221;localData is updated: &#8221; + beginIdx + &#8220;-&#8221; + (beginIdx + result.length) );            			</p>
<p>			error.dataReady(result);</p>
<p>			if (isDataInit == false)<br />
			{<br />
				isDataInit = true;<br />
				dispatchResetEvent(); // make columns are initialized<br />
			}</p>
<p>			var dataReadyEvent:Event = new Event(&#8221;DataReady&#8221;);<br />
			dispatchEvent(dataReadyEvent);</p>
<p>		}</p>
<p>		private function cleanInvisiblePages(page:int):void<br />
		{<br />
			trace(&#8221;start cleaning&#8221;);<br />
			for (var k:int = 0; k  (page+1) || k  length) ? length : end;</p>
<p>					for (var i:int = start; i</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Marcus Williford</title>
		<link>http://blog.widget-labs.com/2007/01/21/new-version-of-remotelist-ilist-implementation-that-support-paging/#comment-1168</link>
		<author>Marcus Williford</author>
		<pubDate>Wed, 27 Feb 2008 03:56:57 +0000</pubDate>
		<guid>http://blog.widget-labs.com/2007/01/21/new-version-of-remotelist-ilist-implementation-that-support-paging/#comment-1168</guid>
		<description>Thanks for posting this code, it is a great contribution.  I added sort for my tests.

I just implemented sort by wrapping the RemoteList and extending ListViewCollection, which dataGrid wraps anyways.  I extend set sort and get sort, and mess with the the query that gets issued against my webcall.  I also had to add some refresh() logic to removeAll data and make sure the CollectionChange events fire properly so the grid will see the new data after the sort/refresh() gets executed.

Other modifications and notes:

1.  I added the dataField to the datagridcolumn (even though I was using an itemrenderer and didn't need it), so it would have something in the "name" column of the SortField.  This is important to capture which field the user selected for sort.  The override means the sort object will get passed when datagrid headers are selected.
2.  I added set sort to the interface and other classes, so my implementation of RemoteDataSet gets the sort object.  Now I can use this sort object to influence my query string that I build (for my xml service).  I sort on the server side, so I only pull what the user is viewing.
3.  I went back and fourth regarding itemPendingError, tried both ways, I almost like the fake "loading" objects better in some ways. 
4.  Datagrid will call set sort(value:Sort) and refresh() on this class, just make sure that alters your webservice query, invalidates data, updates a new length, then throws a collectionchange event.


RemoteCollectionView class ( to be used as a sort capable wrapper) instead of RemoteList.
-------------------------------------------------------
{
	import mx.collections.ICollectionView;
	import mx.collections.ListCollectionView;
	import mx.collections.Sort;

	public class RemoteCollectionView extends ListCollectionView implements ICollectionView
	{
		
		/**
		 * 
		 * Utilize ListCollectionView for most operations, only override what we need to to add sort functionality
		 * 
		 **/
		public function RemoteCollectionView(rList:RemoteList)
			{
			super(rList);
			
		}
		
		public function set query(value:String):void {
			RemoteList(this.list).query = value;
		}

		private var _sort:Sort;
		
		public var sortField:String;
		public var descending:Boolean;
	
 		override public function get sort():Sort {
 			return null; // never use internal sort to sort this remote collection
 		}
 		override public function set sort(value:Sort):void
		{
			_sort = value;
			RemoteList(this.list).sort = _sort;
		}
		
		override public function refresh():Boolean {
			RemoteList(this.list).refresh();
			return true;
		}
	}
}

I'll try to wrap this up into a project or something when I get more time.  I just wanted to share these modifications, as it really worked out great.

Thanks,
Marcus Williford</description>
		<content:encoded><![CDATA[<p>Thanks for posting this code, it is a great contribution.  I added sort for my tests.</p>
<p>I just implemented sort by wrapping the RemoteList and extending ListViewCollection, which dataGrid wraps anyways.  I extend set sort and get sort, and mess with the the query that gets issued against my webcall.  I also had to add some refresh() logic to removeAll data and make sure the CollectionChange events fire properly so the grid will see the new data after the sort/refresh() gets executed.</p>
<p>Other modifications and notes:</p>
<p>1.  I added the dataField to the datagridcolumn (even though I was using an itemrenderer and didn&#8217;t need it), so it would have something in the &#8220;name&#8221; column of the SortField.  This is important to capture which field the user selected for sort.  The override means the sort object will get passed when datagrid headers are selected.<br />
2.  I added set sort to the interface and other classes, so my implementation of RemoteDataSet gets the sort object.  Now I can use this sort object to influence my query string that I build (for my xml service).  I sort on the server side, so I only pull what the user is viewing.<br />
3.  I went back and fourth regarding itemPendingError, tried both ways, I almost like the fake &#8220;loading&#8221; objects better in some ways.<br />
4.  Datagrid will call set sort(value:Sort) and refresh() on this class, just make sure that alters your webservice query, invalidates data, updates a new length, then throws a collectionchange event.</p>
<p>RemoteCollectionView class ( to be used as a sort capable wrapper) instead of RemoteList.<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
{<br />
	import mx.collections.ICollectionView;<br />
	import mx.collections.ListCollectionView;<br />
	import mx.collections.Sort;</p>
<p>	public class RemoteCollectionView extends ListCollectionView implements ICollectionView<br />
	{</p>
<p>		/**<br />
		 *<br />
		 * Utilize ListCollectionView for most operations, only override what we need to to add sort functionality<br />
		 *<br />
		 **/<br />
		public function RemoteCollectionView(rList:RemoteList)<br />
			{<br />
			super(rList);</p>
<p>		}</p>
<p>		public function set query(value:String):void {<br />
			RemoteList(this.list).query = value;<br />
		}</p>
<p>		private var _sort:Sort;</p>
<p>		public var sortField:String;<br />
		public var descending:Boolean;</p>
<p> 		override public function get sort():Sort {<br />
 			return null; // never use internal sort to sort this remote collection<br />
 		}<br />
 		override public function set sort(value:Sort):void<br />
		{<br />
			_sort = value;<br />
			RemoteList(this.list).sort = _sort;<br />
		}</p>
<p>		override public function refresh():Boolean {<br />
			RemoteList(this.list).refresh();<br />
			return true;<br />
		}<br />
	}<br />
}</p>
<p>I&#8217;ll try to wrap this up into a project or something when I get more time.  I just wanted to share these modifications, as it really worked out great.</p>
<p>Thanks,<br />
Marcus Williford</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: blog.widget-labs.com &#187; Blog Archive &#187; Short update on RemoteList implementation</title>
		<link>http://blog.widget-labs.com/2007/01/21/new-version-of-remotelist-ilist-implementation-that-support-paging/#comment-9</link>
		<author>blog.widget-labs.com &#187; Blog Archive &#187; Short update on RemoteList implementation</author>
		<pubDate>Tue, 13 Mar 2007 02:17:22 +0000</pubDate>
		<guid>http://blog.widget-labs.com/2007/01/21/new-version-of-remotelist-ilist-implementation-that-support-paging/#comment-9</guid>
		<description>[...] short update for RemoteList  [...]</description>
		<content:encoded><![CDATA[<p>[&#8230;] short update for RemoteList  [&#8230;]</p>
]]></content:encoded>
	</item>
</channel>
</rss>
