Wednesday, March 16, 2011

Stump the Evangelists

So back at MAX 2010, there was a stump the evangelists game. There was a call for questions. I submitted a whole bunch, but most weren't used. These questions and their answers are useful to share, because they were intended to stump the people in the know. They all came about because there was significant debugging effort involved in understanding them.

Q1) Which kind of COLLECTION_CHANGE Event (as specified by CollectionKindEvent), does the HierarchicalCollectionView ignore, when dispatched from its hierarchicalData source.
A1) CollectionKindEvent.REFRESH
Reference: HierachicalCollectionView.
collectionChangeHandler() method   -> line 1413; if-else statement
Discovered when trying to apply filtering to an array collection that gets mapped to hierachicalData




Q2)  Why do you see columns A&B and not just A in the following example:

<?xml version="1.0" encoding="utf-8"?>
<mx:AdvancedDataGrid xmlns:fx="http://ns.adobe.com/mxml/2009"
                     xmlns:s="library://ns.adobe.com/flex/spark"
                     xmlns:mx="library://ns.adobe.com/flex/mx"
                     currentState="A"
                     >
    <mx:states>
        <s:State name="A" />
        <s:State name="B" />
    </mx:states>
   
    <mx:columns>
        <mx:AdvancedDataGridColumn dataField="A" />
        <mx:AdvancedDataGridColumn dataField="B" />
    </mx:columns>
   
    <mx:columns.A>
        <mx:AdvancedDataGridColumn dataField="A" />
    </mx:columns.A>
   
    <mx:columns.B>
        <mx:AdvancedDataGridColumn dataField="B" />
    </mx:columns.B>
</mx:AdvancedDataGrid>

A2) The problem is with commitProperties. currentState gets set in UIComponent's commitProperties, but  in AdvancedDataGridBaseEx.commitProperties(), createDisplayableColumns is called BEFORE super.commitProperties(). This means that the columns get set before the state, which SHOULD cause them to reset, but since we are currently within the commitProperties method, the invalidateProperties flag does NOT get triggered again (to avoid an infinite loop), even though the columnChanged flag gets set. CommitProperties doesn't run again until an external event which causes invalidateProperties to be set.





Q3) Within a single collection displayed in an editable column of an editable AdvancedDataGrid, you have a property that is sometimes editable and sometimes not (for example, you cannot purchase quantity to an out of stock item, even though it still shows up on the catalog). What tricks can you employ to have the ADG skip over the non-editable cells when using keyboard navigation?

A3) There is nothing you can do on the renderer/editor to prevent this. This cell will still receive focus from keyboard navigation, because of the findNextItemRenderer() method within AdvancedDataGridBase. Even if there are no focusable elements within the cell. Nor can you pass focus to the next element via the focusManager as the grid doesn't respond to non-keyboard or mouse focus events. The ONLY point of entry (ie: public or protected properties or methods) to which you have access to cause focus to skip over this renderer is the  protected function isDataEditable(data:Object):Boolean defined on AdvancedDataGridBase. You MUST extend the ADG and override this method in order to be able to set up your grid to skip particular cells.

Q4.1) Not using Flash Player 10.1, how can you catch a majority of thrown errors within the Flex component lifecycle.
A4.1) UIComponentGlobals.catchCallLaterExceptions = true

Q4.2) With UIComponentGlobals.catchCallLaterExceptions set to true, what errors do NOT get caught?
A4.2) Errors that happen within EventListeners

Q4.3) With Flash Player 10.1, how can you catch all errors
A4.3) loaderInfo["uncaughtErrorEvents"].addEventListener("uncaughtError",globalExeptionCatcher) //at the time being, there is / should be a way with strongly typed values to do this later.


Q5) How do I see a traceLog of all of the Bindings that are firing?
A5) BindingManager.debugBinding()

Q6) What is the value of the updateCount from the following code?
<?xml version="1.0" encoding="utf-8"?>
<s:myComp xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx"
               creationComplete="onCreationComplete()"
               >
    <fx:Script>
        <![CDATA[
            private var _myProp:Number = 1;
            private var updateCount:Number = 0;
           
            [Bindable]
            public function get myProp():Number {return _myProp;}
            public function set myProp(v:Number):void
            {
                _myProp = v;
                updateCount++;
            }
           
            private function onCreationComplete():void
            {
                myProp = 1;
            }
        ]]>
    </fx:Script>
   
</s:myComp>
A6) 0. The binding doesn't fire if the getter returns the same value as what you are setting. You would need to manually dispatch an event within the setter and set the event metadata within the binding to get the updateCount value to change to 1

Q7) How must you create Bindings on implict getters and setters within an interface?
package
{
    interface IExample
    {
        function get propA():String;
        function set propA(v:String):void;
    }
}

A7) You must use explict events within the bindings tag, otherwise bindings will never fire in the implementations
package
{
    interface IExample
    {
        [Bindable(event="propAChanged")]
        function get propA():String;
        function set propA(v:String):void;
    }
}


Q8) What are any of the non-standard practices (related to the flex framework as a whole) regarding the hover state in the MxAdvancedDataGridItemRenderer that make it extremely difficult to extend this class and modify the hover functionality?

A8)        * hovered property is being set in the "invalidateProperties" method instead of the "commitProperties" method.
             * actually it is super.hovered that is being set, elminating the ability to override it
             * when hovered IS being set, the state change happends via "setCurrentState()" method instead of "currentState" property
             * hovered is determined from "listBase.isItemHighlighted(data);"... ie the renderer asks the grid. this supercedes any value that is passed in manually
             * hovered property doesn't actually get set (in the super clases) if the currentState is already "hovered".

No comments:

Post a Comment