Link to home
Start Free TrialLog in
Avatar of RSA_KM_TEAM
RSA_KM_TEAM

asked on

Struggling filtering an XMLList from another XMLList (Actionscript 3.0)

Hi,

I'm trying to build something of a document library at work.  There will probably be two main filters (insurance class and type of document) which I'd like users to be able to select to filter the list of documents.

I've been trying to have two list boxes at the top interact using XMLLists and DataProviders.  Something very similar in fact to the Adobe Video Workshop - the way they have the two selections above the list of videos.  

I've enclosed the code below of where I'm upto.  I can get it to display both lists (XML at the bottom), but I'd like to be able to say click on Property and have the second list reflect only document types applicable to Property.

On my stage i have the businessDP and typeDP lists.  

Hope this makes sense, if I need to post anymore I will!

Thanks,
John  
import fl.data.DataProvider;
 
var selectedBusiness:Object = new Object();
var selectedType:Object = new Object();
var businesses:XMLList = new XMLList();
var types:XMLList = new XMLList();
 
var businessDP:DataProvider = new DataProvider();
business.dataProvider = businessDP;
business.addEventListener(Event.CHANGE, changeBusiness);
 
var typeDP:DataProvider = new DataProvider();
type.dataProvider = typeDP;
type.addEventListener(Event.CHANGE, changeType);
 
function changeBusiness(event:Object):void {
	selectedBusiness = business.selectedItem;
} 	
 
function changeType(event:Object):void {
	selectedType = type.selectedItem;
} 	
 
// load the XML file
var myXMLLoader:URLLoader = new URLLoader();
myXMLLoader.load(new URLRequest("assets/SampleDocLibrary.xml"));
myXMLLoader.addEventListener(Event.COMPLETE, myXMLLoadedHandler);
 
function myXMLLoadedHandler(eventObj:Event):void {
	var businessXML = new XML(eventObj.currentTarget.data);
	businesses = businessXML.children()[0].children();	
	
	var typesXML = new XML(eventObj.currentTarget.data);
	types = typesXML.children()[1].children();	
	
	setBusinesses();
	setTypes();
	//typeText.text = typesXML.children().children()[6];
}
 
function setBusinesses():void {
	var i:int = 0;
	for each(var prop:XML in businesses) {
		var businessData:XML = prop;
		businessDP.addItem( { label:businessData.@label, data:businessData.@data } );
		i++;
	}	
	selectedBusiness = business.dataProvider.getItemAt(0);
}
 
function setTypes():void {
	var i:int = 0;
	for each(var prop:XML in types) {
		var typeData:XML = prop;
		typeDP.addItem( { label:typeData.@name, data:typeData.@code } );
		i++;
	}	
	selectedType = type.dataProvider.getItemAt(0);
}
 
 
<!---------------------------------------- XML ---------------------------------------->
 
<dataset>
	<businesses>
		<business label="Property" data="prop"/>
		<business label="Liability" data="liab"/>
		<business label="Household" data="hous"/>
		<business label="Motor" data="moto"/>
		<business label="ProFin" data="prof"/>
		<business label="Marine" data="mari"/>
	</businesses>
	<types>
		<type name="British Standard" code="bs" lob="prop"/>
		<type name="Guide" code="gd" lob="liab"/>
	</types>
</dataset>

Open in new window

Avatar of OlaMuldal
OlaMuldal

You can filter directly from your XML data with E4X, and apply it to the DataProvider for the buisnessList.

Examples

I wrote some code loosely based on your sample. Create a new ActionScript 3 document and drag the List component into the library, then paste this code in the first frame.

import fl.data.DataProvider;
import fl.controls.List;
 
 
/**
 *	Data
 */
 
var data:XML =
<dataset>
	<businesses>
		<business label="Property" data="prop"/>
		<business label="Liability" data="liab"/>
		<business label="Household" data="hous"/>
		<business label="Motor" data="moto"/>
		<business label="ProFin" data="prof"/>
		<business label="Marine" data="mari"/>
	</businesses>
	<types>
		<type name="British Standard" code="bs" lob="prop"/>
		<type name="Guide" code="gd" lob="liab"/>
	</types>
</dataset>;
 
 
/**
 *	Setup List controls
 */
 
var typeList:List = createList();
var buisnessList:List = createList();
 
typeList.x = 10;
buisnessList.x = 220;
typeList.y = buisnessList.y = 10;
 
function createList():List {
	var list:List = new List();
	list.width = 200;
	list.height = 300;
	addChild(list);
	return list;
}
 
typeList.labelField = "name";
buisnessList.labelField = "label";
 
typeList.addEventListener(MouseEvent.CLICK, filterBuisness);
 
 
/**
 *	Integrate data providers
 */
 
typeList.dataProvider = new DataProvider(data.types[0]);
 
function filterBuisness(event:MouseEvent = null):void {
	
	
	if (typeList.selectedIndex == -1) {
		
		// If no type is selected, view all businesses
		buisnessList.dataProvider = new DataProvider(data.businesses[0]);
		
	} else {
		
		// Else, filter by the lob attribute in types
		var filteredXMLList:XMLList = data.businesses[0].business.(@data == typeList.selectedItem.lob);
		
		// Make an XML object for the dataprovider
		var filteredXML:XML = XML(<data/>).setChildren(filteredXMLList);
		
		// Set the new data
		buisnessList.dataProvider = new DataProvider(filteredXML);
		
	}
}
 
// Run filter on initialization
filterBuisness();

Open in new window

Avatar of RSA_KM_TEAM

ASKER

Hey OlaMudal,

Thanks so much, that's really helpful.

I'm trying to keep the xml file external, it's going to be really large when finished I think, so I'm trying to take the above and apply it to an external file, but not succeeding!

I'm very new to actionscript/flash and especially with using XML within it, so apologies if there is something very basic I'm doing incorrectly!  Can you help further?

Thanks,
John
ASKER CERTIFIED SOLUTION
Avatar of OlaMuldal
OlaMuldal

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
That's absolutely solved my issues.

Thank you Ola.