Thursday, January 6, 2011

Search through XML database using AS3: Part 4

Today we'll apply the search feature to a data grid instead of a list component.

Here's how it is going to look:


Firstly, take off the list component off the stage and replace it with a data grid component. Give it an instance name of myGrid.

Now, because the component already has sorting feature pre-built, we can remove all the buttons needed for sorting and all the code with it.

Then we create columns for the grid:

import fl.controls.dataGridClasses.DataGridColumn;

var col_fname:DataGridColumn = new DataGridColumn("First");
myGrid.addColumn(col_fname);

var col_lname:DataGridColumn = new DataGridColumn("Last");
myGrid.addColumn(col_lname);

var col_age:DataGridColumn = new DataGridColumn("Age");
myGrid.addColumn(col_age);
col_age.sortOptions = Array.NUMERIC;
col_age.width=35

var col_sex:DataGridColumn = new DataGridColumn("Sex");
myGrid.addColumn(col_sex);
col_sex.width=50

var col_job:DataGridColumn = new DataGridColumn("Job");
myGrid.addColumn(col_job);

Now we will change the updateList function to work with the datagrid:

function updateList():void
{
myGrid.dataProvider = new DataProvider ();

for (var i:int = 0; i<currentUserbase.length; i++)
{
myGrid.addItem({First: currentUserbase[i].firstname, Last: currentUserbase[i].secondname, Age: currentUserbase[i].age, Sex: currentUserbase[i].sex, Job: currentUserbase[i].job});
}
}

And here's the full code:

import fl.data.DataProvider;
import fl.controls.dataGridClasses.DataGridColumn;

var col_fname:DataGridColumn = new DataGridColumn("First");
myGrid.addColumn(col_fname);

var col_lname:DataGridColumn = new DataGridColumn("Last");
myGrid.addColumn(col_lname);

var col_age:DataGridColumn = new DataGridColumn("Age");
myGrid.addColumn(col_age);
col_age.sortOptions = Array.NUMERIC;
col_age.width=35

var col_sex:DataGridColumn = new DataGridColumn("Sex");
myGrid.addColumn(col_sex);
col_sex.width=50

var col_job:DataGridColumn = new DataGridColumn("Job");
myGrid.addColumn(col_job);

var allUserbase:Array = [];// contains all users like in xml
var currentUserbase:Array = [];// contains users that need to be displayed

var _loader:URLLoader = new URLLoader();
var _data:XML = new XML();

_loader.addEventListener(Event.COMPLETE, readXML);
_loader.load(new URLRequest("userbase.xml"));

function readXML(event:Event):void
{
_data = new XML(event.target.data);
for each (var usr in _data.user)
{
allUserbase.push({id: usr.@id, firstname: usr.@firstname, secondname: usr.@secondname, sex: usr.@sex, age: usr.@age, job: usr.@job});
}
currentUserbase = allUserbase.concat();
updateList();
}

function updateList():void
{
myGrid.dataProvider = new DataProvider ();

for (var i:int = 0; i<currentUserbase.length; i++)
{
myGrid.addItem({First: currentUserbase[i].firstname, Last: currentUserbase[i].secondname, Age: currentUserbase[i].age, Sex: currentUserbase[i].sex, Job: currentUserbase[i].job});
}
}

// Search:

search_firstname.text = "";
search_firstname.restrict = "A-Za-z";
search_secondname.text = "";
search_secondname.restrict = "A-Za-z";
search_sex.dataProvider = new DataProvider([{label:"Any",data:"Any"},{label:"Male",data:"Male"},{label:"Female",data:"Female"}]);
search_age.text = "";
search_age.restrict = "0-9";
search_job.text = "";
search_job.restrict = "A-Za-z ";

var pattern_firstname:RegExp;
var pattern_secondname:RegExp;
var pattern_job:RegExp;

bt_search.addEventListener(MouseEvent.CLICK, search);

function search(MouseEvent):void
{
currentUserbase = [];

pattern_firstname = new RegExp(search_firstname.text);
pattern_secondname = new RegExp(search_secondname.text);
pattern_job = new RegExp(search_job.text);

for (var n:int = 0; n<allUserbase.length; n++)
{
if ((pattern_firstname.test(allUserbase[n].firstname) || search_firstname.text=="") && (pattern_secondname.test(allUserbase[n].secondname) || search_secondname.text=="") && (allUserbase[n].sex == search_sex.selectedItem.data || search_sex.selectedItem.data=="Any") && (allUserbase[n].age == search_age.text || search_age.text=="") && (pattern_job.test(allUserbase[n].job) || search_job.text==""))
{
currentUserbase.push(allUserbase[n]);
}
}
updateList();
}

Thanks for reading!

Related:

Search through XML database using AS3: Part 1
Search through XML database using AS3: Part 2
Search through XML database using AS3: Part 3
Search through XML database using AS3: Part 5
Search through XML database using AS3: Part 6

14 comments:

Anonymous said...

Hi there,
Its a great blog. I have learned a lot from here. Thanks for posting awesome materials..

I have a question though I am working on same kind of assignment, I have to search through XML and display the searched data. The problem I am facing is that my xml somewhat looks like this:



nh789
ui989



ty779
55489
55489



ty779




I have to search through complexes and display the corresponding name and state in the datagrid. I am unable to search these multi-xml nodes with same name. Any help would be really great. Thanks a lot in advance.

Anna

Blue leaf -{:) said...
This comment has been removed by the author.
Anonymous said...

gh345



ty345
rt745



uy235
bn875
lk655

Anonymous said...

man i am totally messing here..just trying to post the xml..not sure why i am not able to.. :(

Kirill Poletaev said...

You can e-mail me the contents and I'll take a look at it.

tmcanally said...

I accidentally posted my question on part 3 of this tutorial. I meant to post it on this one (part 4) since it involves the datagrid component.

Please see part 3. Thanks.

Kirill Poletaev said...

First of all go to the XML file and create an attribute for each user item called "rowcolor" and set it to a color value like this:

rowcolor="0xff0000"

After that, go to the main .fla file and set each column's cellRenderer to fontCellRenderer.

Like this:

col_fname.cellRenderer = fontCellRenderer;

Do this with every column you have.

Now in readXML(), in the loop where you create new array elements, add a new property "RowColor" that takes value from XML's "rowcolor":

for each (var usr in _data.user)
{
allUserbase.push({id: usr.@id, firstname: usr.@firstname, secondname: usr.@secondname, sex: usr.@sex, age: usr.@age, job: usr.@job, RowColor: usr.@rowcolor});
}

Then go to updateList() function and set RowColor property of the newly created data grid item in the loop to RowColor from the array:

for (var i:int = 0; i<currentUserbase.length; i++)
{
myGrid.addItem({First: currentUserbase[i].firstname, Last: currentUserbase[i].secondname, Age: currentUserbase[i].age, Sex: currentUserbase[i].sex, Job: currentUserbase[i].job, RowColor: currentUserbase[i].RowColor});
}

Finally, create a new file in the same directory called fontCellRenderer.as with the code:

package
{

import fl.controls.listClasses.CellRenderer;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;

public class fontCellRenderer extends CellRenderer
{

public function fontCellRenderer()
{
}

override protected function drawBackground():void
{
var tf:TextFormat = new TextFormat();
tf.color = data.RowColor;
setStyle("textFormat", tf);
super.drawBackground();
}

}
}



What I did is basically set a custom cell renderer for each cell in the datagrid, that reads the "RowColor" value from the current data object (the data object is shared for the entire row) and sets the font color of the text to that color value. This way you can also set other style properties like size, weight, etc.

Good luck!

tmcanally said...

Thank you SO MUCH!!! It worked. I already had a TextFormat applied, but I was able to move that textformat in the .as file. My managers and supervisors are THRILLED! I can't thank you enough!

tmcanally said...

If I had two dynamic text boxes ("myLine1" and "myLine2") and two extra lines in my userbase that I wanted to use as the text for those text boxes, how would I do that?

Here is the userbase text:






How would I get "Test Line 1" in the first textbox and "Test Line 2" in the second text box?

(The rest of the userbase supplies the data for the datagrid component, but since these "identifiers" (projname=) are different they will not be shown in the datagrid.

Please help!

tmcanally said...
This comment has been removed by the author.
tmcanally said...

I am having trouble posting the userbase code.
Let me try it this way:

"?xml version="1.0" encoding="UTF-8" standalone="yes"?"
"userbase"
"user id="ProjLine1" projname="Test Line 1" /"
"user id="ProjLine2" projname="Test Line 2" /"
"/userbase"

Kirill Poletaev said...

You can read the data from those nodes by filtering the XML by "id" attribtue.

Read more about XML filtering:

http://kirill-poletaev.blogspot.com/2010/09/working-with-xml-data-using-as3-part-5.html

tmcanally said...

How would I apply that to a text box?

Let's say the instance name was myTextBox1 and myTextBox2; and the userbase code is exactly as it is above.

myTextBox1.text = ???
myTextBox2.text = ???

Kirill Poletaev said...

myTextBox1.text = _data.user.(@id=="ProjLine1").@projname;
myTextBox2.text = _data.user.(@id=="ProjLine2").@projname;

Haven't tested it but it should work

Post a Comment