Keeping selectedIndex list between data reloads in Flex

In my Flex frontend, I have several List components that are bound to an ArrayCollections array. I find that when ArrayCollections are updated (via web services) and the data bindings to update the lists, each List is reset and its selectedIndex is discarded. This is a problem if the user is in the middle of a task and has already selected an item in the list but has not yet submitted the form.

I know how I can combine some ActionScript to handle these cases, but do you know of any way to deal with this more naturally using Flex data bindings or generic event utilities?

Thanks as always!

+1


source to share


2 answers


I like to use the watch class found here to call a function when data changes. It takes two parameters: data to view and a function to call. (Keeps repeating setters and getters all the time)



I would keep the selected item when it is selected, and when the data is refreshed, reselect that item by going down the list and selecting the item again.

+1


source


We have a SelectionRestorer class that does exactly that. Just add it to MXML and set a target for it in the list / combobox / whatever you want to repopulate and it is all watching you.

NTN,

Sam




We are hiring! Developers and QA in Washington DC (or want to relocate) should send a resume to careers@blinemedical.com.




package com.atellis.common.controls {
import flash.events.Event;
import flash.events.EventDispatcher;

import mx.events.CollectionEvent;
import mx.events.ListEvent;

public class SelectionRestorer extends EventDispatcher
{
    private var previousSelectedItems:Array;

    private var _compareField:String;
    [Bindable("compareFieldChanged")]
    public function get compareField():String {
        return _compareField;
    }
    public function set compareField(value:String):void {
        _compareField = value;
        dispatchEvent(new Event("compareFieldChanged"));
    }

    private var _compareFunction:Function;
    [Bindable("compareFunctionChanged")]
    public function get compareFunction():Function {
        return _compareFunction;
    }
    public function set compareFunction(value:Function):void {
        _compareFunction = value;
        dispatchEvent(new Event("compareFunctionChanged"));
    }

    private var _target:Object;
    [Bindable("targetChanged")]
    public function get target():Object {
        return _target;
    }

    public function set target(value:Object):void {
        if (_target) {
            if (_target.dataProvider) {
                _target.dataProvider.removeEventListener(CollectionEvent.COLLECTION_CHANGE, dataChangeHandler);
            }
            _target.removeEventListener(ListEvent.CHANGE, selectionChangeHandler);
            _target.removeEventListener(CollectionEvent.COLLECTION_CHANGE, dataChangeHandler);              
        }
        _target = value;
        if (value) {
            value.addEventListener(ListEvent.CHANGE, selectionChangeHandler, false, 0, true);
            value.addEventListener(CollectionEvent.COLLECTION_CHANGE, dataChangeHandler, false, 100.0, true);
            if (value.dataProvider) {
                value.dataProvider.addEventListener(CollectionEvent.COLLECTION_CHANGE, dataChangeHandler, false, 100.0, true);
            }
        }
        dispatchEvent(new Event("targetChanged"));
    }

    public function refresh():void {
        if (useMultipleSelect) {
            previousSelectedItems = target.selectedItems;
        } else {
            previousSelectedItems = [target.selectedItem];
        }
    }

    public function clear():void {
        previousSelectedItems = null;
    }

    private function compareFieldFunction(o1:Object, o2:Object):Boolean {
        if (o1 == null || o2 == null) {
            return false;
        }
        var v1:Object = o1[compareField];
        var v2:Object = o2[compareField];
        return v1 != null && v2 != null && v1 == v2;                
    }

    private function compareEqualityFunction(o1:Object, o2:Object):Boolean {
        if (o1 == null || o2 == null) {
            return false;
        }
        return o1 == o2;                
    }

    private function get useMultipleSelect():Boolean {
        return "selectedItems" in target && "allowMultipleSelection" in target && target.allowMultipleSelection;
    }

    private function selectionChangeHandler(event:ListEvent):void {
        refresh();
    }

    private function dataChangeHandler(event:CollectionEvent):void {

        if (previousSelectedItems == null || previousSelectedItems.length == 0) {
            return;
        }

        if (target.dataProvider == null) {
            previousSelectedItems = null;
            return;
        }

        var comparer:Function = compareFunction;

        if (comparer == null) {
            if (compareField == null) {
                comparer = compareEqualityFunction;
            } else {
                comparer = compareFieldFunction;
            }
        }

        // when you assign an array to ListBase.selectedItems, it removes all items from the array,
        // so we need to build two arrays, one to assign, and one for current state
        var indices:Array = new Array();
        var items:Array = new Array();
        var dpIndex:int = 0;            
        for each(var newItem:Object in target.dataProvider) {
            for(var i:int = 0; i<previousSelectedItems.length; i++) {
                if (comparer(newItem, previousSelectedItems[i])) {
                    indices.push(dpIndex);
                    items.push(newItem);
                    previousSelectedItems.splice(i, 1);
                    break;
                }                       
            }
            if (previousSelectedItems.length == 0) {
                break;
            }
            dpIndex++;
        }
        target.validateNow();

        if (useMultipleSelect) {
            target.selectedIndices = indices;
        } else {
            target.selectedIndex = indices[0];
        }

        if (items.length) {
            previousSelectedItems = items;
        } else {
            previousSelectedItems = null;
        }
    }               
}
}

      

+1


source







All Articles