20 Replies Latest reply on Jan 31, 2011 11:58 PM by TomBurgundy

    How to update nested ListCollectionViews?

    TomBurgundy Level 1

      Hi troops,

       

      my application has a core set of items (e.g. Products), which gets passed between various view layers. Each layer wraps a given input list in a ListCollectionView, and adds its own sorting and filtering.

       

      That way I might have a construct similar to

       

      new ListCollectionView(new ListCollectionView(new ArrayCollection()))

       

      but, of course, with sorting/filtering added on each level.

       

      Now when I call itemUpdated() on the root ArrayCollection, then this change does not propagate properly up the hierarchy of lists.

       

      It seems that for each wrapping, I have to call itemUpdated(), such as:

       

      ac.itemUpdated(product);

      ac.itemUpdated(product);

       

      to make the top-most ListCollectionView update. A single call does not do the trick.

       

      Debugging into the code gave me the insight that the initial CollectionEvent.UPDATE event from the AC is converted into a MOVE event by the ListCollectionView. The second call then makes the LCV realize that the item wouldn't move anymore and does not convert the event, so that the next LCV can do a item-moved update of its localIndex.

       

      Yes, yes, very complicated. Any feedback welcome, of course

        • 1. Re: How to update nested ListCollectionViews?
          Flex harUI Adobe Employee

          For a single original set of data, if you want multiple views (with

          different filters and sorts), you share the list or the source.  If you

          share the list, then changes to the list are propagated to all views.

           

          Original data:

          Var arr:Array = ["Foo", "Bar", "Baz"];

          Var ac:ArrayCollection = new ArrayCollection(arr);

          Var view1:ListCollectionView = new ListCollectionView();

          view1.list = ac.list;

          Var view2:ListCollectionView = new ListCollectionView();

          view2.list = ac.list;

          • 2. Re: How to update nested ListCollectionViews?
            TomBurgundy Level 1

            Yes, I know. If you look at the constructor for LIstCollectionView, then you will see that what you wrote is pretty much what I wrote in my original post.

             

            Now how does your post answer my question?

            • 4. Re: How to update nested ListCollectionViews?
              TomBurgundy Level 1

              From that discussion thread above I could derive that in Flex the CollectionEventKind MOVE should be interpreted as being an UPDATE plus a move.

               

              The bug would then be clearly in the ListCollectionView class, where it is ignoring any MOVE event altogether! See listChangeHandler() function, line 1089, Flex SDK 3.5

              • 5. Re: How to update nested ListCollectionViews?
                TomBurgundy Level 1

                Any word from Adobe?

                • 6. Re: How to update nested ListCollectionViews?
                  Flex harUI Adobe Employee

                  I'm not sure what you tried and what I suggested are the same thing.  Did

                  you try what I suggested?

                  • 7. Re: How to update nested ListCollectionViews?
                    TomBurgundy Level 1

                    Here is an example of what drives me crazy. Points to note:

                    • it occurs on an ArrayCollection if it is wrapped with LCVs at least twice
                    • the first LCV must have a sort, the other must have a declared filter function
                    • calling itemUdpated twice gives the desired effect of showing the new order of items, but calling it only once doesnt

                     

                    Run the code with the 2nd itemUpdate() call commented or not and see the difference in the output.

                     

                    <?xml version="1.0" encoding="utf-8"?>
                    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" 
                         minWidth="955" minHeight="600"
                         creationComplete="run()"
                         >
                         
                         <mx:Script>
                         <![CDATA[
                              import model.Product;
                              
                              import mx.collections.ArrayCollection;
                              import mx.collections.IList;
                              import mx.collections.ListCollectionView;
                              import mx.collections.Sort;
                              import mx.collections.SortField;
                    
                              
                              protected function run() : void
                              {
                                   var ac:ArrayCollection = new ArrayCollection();
                                   ac.addItem(new Product("bottom", 0));
                                   ac.addItem(new Product("top", 1000));
                                   
                                   var lcv:ListCollectionView = new ListCollectionView(ac);
                                   lcv.sort = new Sort();
                                   lcv.sort.fields = [ new SortField('rank', false, true) ];
                                   lcv.refresh();
                    
                                   var lcv2:ListCollectionView = new ListCollectionView(lcv);
                                   lcv2.filterFunction = function(item:Object) : Boolean { return true; };
                                   lcv2.refresh();
                                   
                                   this.traceList(lcv2);
                                   
                                   var p:Product = new Product("new", 2000);
                                   ac.addItem(p);
                                   
                                   this.traceList(lcv2);
                                   
                                   p.rank = -999;
                                   
                                   ac.itemUpdated(p);
                                   ac.itemUpdated(p);
                                   this.traceList(lcv2);
                              }
                              
                              protected function traceList(list:IList) : void
                              {
                                   var output:String = "";
                                   for each (var item:Object in list) {
                                        if (output.length > 0)
                                             output += ", ";
                                        output += item.toString();
                                   }
                                   trace(output);
                              }
                         ]]>
                         </mx:Script>
                    </mx:Application>
                     
                    

                     

                    and model class Product

                     

                    package model
                    {
                         import mx.utils.StringUtil;
                    
                         public class Product
                         {
                              public var title:String;
                              public var rank:Number;
                              
                              
                              public function Product(title:String=null, rank:Number=NaN)
                              {
                                   this.title = title;
                                   this.rank = rank;
                              }
                              
                              
                              public function toString() : String
                              {
                                   return StringUtil.substitute("Product [title={0}, rank={1}]", this.title, this.rank);
                              }
                         }
                    }
                    
                    

                    • 8. Re: How to update nested ListCollectionViews?
                      TomBurgundy Level 1

                      It would be really great to get feedback on this from Adobe to restore my trust into the collections classes - the building block of my application..

                      • 10. Re: How to update nested ListCollectionViews?
                        JabbyPandaUA Level 3

                        AFAIK ListCollectionView is an ugly duck in Flex SDK (approx 30 open/deferred bugs in Adobe JIRA connected to ListCollectionView), avoid it if you can and revert to filtering/sorting a custom copy of ArrayCollection instead.

                         

                        Like Tink is doing http://www.tink.ws/blog/collectionclone/

                         

                        Or patch ListCollectionView by yourself 

                        • 11. Re: How to update nested ListCollectionViews?
                          Flex harUI Adobe Employee

                          Sorry, there is a lot of traffic on this forum and sometimes things get lost

                          in the shuffle.

                           

                          I walked through your test case.  I agree it is a bug.  Please file it at

                          http://bugs.adobe.com/jira.

                           

                          I would share the ILists and avoid nesting by combining the sort and filter

                          on one of the LCVs.

                           

                                      protected function run() : void

                                      {

                                          var ac:ArrayCollection = new ArrayCollection();

                                          ac.addItem(new Product("bottom", 0));

                                          ac.addItem(new Product("top", 1000));

                                           

                                          var lcv:ListCollectionView = new

                          ListCollectionView(ac.list);

                                          lcv.sort = new Sort();

                                          lcv.sort.fields = ;

                                          lcv.refresh();

                                          this.traceList(lcv);

                                           

                                          var lcv2:ListCollectionView = new

                          ListCollectionView(ac.list);

                                          lcv2.sort = new Sort();

                                          lcv2.sort.fields = ;

                                          lcv2.filterFunction = function(item:Object) : Boolean {

                          return true; };

                                          lcv2.refresh();

                                           

                                          this.traceList(lcv2);

                                           

                                          var p:Product = new Product("new", 2000);

                                          ac.addItem(p);

                                           

                                          this.traceList(lcv2);

                                           

                                          p.rank = -999;

                                           

                                          ac.itemUpdated(p);

                                          this.traceList(lcv2);

                                      }

                          • 12. Re: How to update nested ListCollectionViews?
                            JabbyPandaUA Level 3

                            TomBurgundy had already logged a corresponding bug into Adobe JIRA 2 weeks ago, no single response from Adobe QA

                             

                            ListCollectionView ignores itemUpdate from wrapped list

                            https://bugs.adobe.com/jira/browse/SDK-27872

                            • 13. Re: How to update nested ListCollectionViews?
                              Flex harUI Adobe Employee

                              We don't always get to the new bugs right away.  I'll add a note to the bug.

                              • 14. Re: How to update nested ListCollectionViews?
                                TomBurgundy Level 1

                                Hi Alex, thanks for this.

                                 

                                Unfortunately your workaround wouldn't be feasible in my application. I use a lot of dependency injection, and lots of ListCollectionView instances get passed around, sometimes adding a wrapping LCV plus filtering/sorting before passing the LCV on to other components.

                                 

                                If I would use your workaround I would have to clone Sort instances and pass them around, together with the filterFunction references, plus the original List reference, which sounds like a nightmare

                                • 15. Re: How to update nested ListCollectionViews?
                                  Flex harUI Adobe Employee

                                  I haven't tried it, but you might be able to catch certain events like that

                                  MOVE and call refresh() again.

                                  • 16. Re: How to update nested ListCollectionViews?
                                    TomBurgundy Level 1

                                    Yes, I could possbily catch some event and dispatch a generic REFRESH.

                                     

                                    But we don't develop the typical nice-to-look-at RIA mini demo-app, but a proper large business application. And calling a REFRESH on a large collection will trigger a whole lot of code to run for each item.

                                     

                                    (removed typo)

                                    • 17. Re: How to update nested ListCollectionViews?
                                      Flex harUI Adobe Employee

                                      Yup.  Another possibility is that you could subclass ListCollectionView,

                                      look for the MOVE and modify the localIndex array appropriately.

                                      • 18. Re: How to update nested ListCollectionViews?
                                        TomBurgundy Level 1

                                        Or somebody from Adobe could take on the responsibility for this bug and post the fix here?

                                        • 19. Re: How to update nested ListCollectionViews?
                                          Flex harUI Adobe Employee

                                          If you campaign for enough votes then it should get fixed in the next

                                          release.