Return ArrayCollection from SELECT query - actionscript-3

In my AIR app i am trying to get the names from sqlite database as an ArrayCollection . Here is my code.
private function visitorName():void {
var sqlText:String = "SELECT name FROM user";
visitorNames = new SQLStatement;
visitorNames.sqlConnection = dbConn;
visitorNames.addEventListener(SQLEvent.RESULT, visitornamesResult);
visitorNames.addEventListener(SQLErrorEvent.ERROR, errorHandler);
visitorNames.text = sqlText;
visitorNames.execute();
}
private function visitornamesResult(event:SQLEvent):Array {
var result:SQLResult = visitorNames.getResult();
var namesList:Array = new Array();
namesList = result.data;
datafield3.dataProvider = namesList;
return namesList;
}
What should i do to get the results to an ArrayCollection by calling the visitorName() function?
Is it possible to get return value from a nested function?I know the visitorName function should be changed to ArrayCollection type and should declare an ArrayCollection variable inside it .. but not so sure how to proceed .. any help appreciated ..

First of all, notice that visitornamesResult is an event handler, so you won't be able to get the return value of that function.
You will want to actually put the result somewhere when you get it (in the UI? or in a model?)
Let's keep it simple, and just assign it to your datafield3.dataProvider:
private function visitorName(): { ... /* same as before */ }
private function visitornamesResult(event:SQLEvent):void {
var result:SQLResult = visitorNames.getResult();
// this is how you create an ArrayCollection with a provided Array
var visitors: ArrayCollection = new ArrayCollection( result.data );
datafield3.dataProvider = visitors;
}

Related

How to access an object in AS3

I wrote this code
var enemies:Object = new Object();
// HP MP ATK DEF MATK MDEF AGI LUCK
enemies.Goblin = [40, 20, 6, 6, 3, 3, 4, 1];
which contains those stats for the goblin and I created a function that should take the stats from enemies.Goblin and put them in some variables but it won't work.
function createEnemy(enemyName:String):void {
e_hp = enemies.enemyName[0];
e_mp = enemies.enemyName[1];
e_atk = enemies.enemyName[2];
e_def = enemies.enemyName[3];
e_matk = enemies.enemyName[4];
e_mdef = enemies.enemyName[5];
e_agi = enemies.enemyName[6];
e_luck = enemies.enemyName[7];
}
This is the output error when the createEnemy function is executed: TypeError: Error #1010: A term is undefined and has no properties.
Object "enemies" does not have "enemyName" property.
Try this:
enemies[enemyName][0]
enemies[enemyName][1]
...
The answer had been given but what are you doing is a wrong way to do. Accessing properties by index is asking for trouble in a very near future.
It is better to do with classes but since you're using objects, I will try use objects too:
var goblin_stats:Object = { hp:40, mp:20, atk:6, def:6 }; // and so on
var elf_stats:Object = { hp:35, mp:30, atk:8, def:4 }; // and so on
...
// add as much characters as needed
Now I believe you just want to create a fresh goblin based on goblin stats. Just pass the stats to the createEnemy function:
createEnemy(goblin_stats);
function createEnemy(stats:Object):void {
e_hp = stats.hp;
e_mp = stats.mp;
// and so on
}
or better:
function createEnemy(stats:Object):void {
for (var property:String in stats) e_stats[property] = stats[property];
}
Store objects (everything) in arrays for easy referencing. Here are the key code:
var aEnemies:Array = new Array();
var mcEnemy:Object = new Object();
mcEnemy.iHP = 40; // set iHP property to 40
aEnemies.push(mcEnemy); // add enemy to array of enemies
trace("enemy 0's HP: " + aEnemies[0].iHP);

AS3 datagrid - Hide a row

I'm using 2 comboboxes to filter a dataGrid that has been populated via csv file. The first combobox filters the columns and works fine:
//Listener and function for when the Agreement ID is selected
agreement_cb.addEventListener(Event.CHANGE, agreement);
function agreement(event:Event):void
{
//get the number of columns
var columnCount:Number = myGrid.getColumnCount();
for (var i:int=0; i<columnCount; i++)
{
myGrid.getColumnAt(i).visible = false;
}
var columnNumber:Number = agreement_cb.selectedItem.data;
myGrid.getColumnAt(columnNumber).visible = true;
myGrid.getColumnAt(0).visible = true;
myGrid.columns[0].width = 200;
}
But I can't find anything on how to get the same type of function to hide all of the rows except the one they select from the second drop-down (codes_cb).
Any help is appreciated...
UPDATE:
loadedData = myLoader.data.split(/\r\n|\n|\r/);
loadedData.pop();
for (var i:int=0; i<loadedData.length; i++)
{
var rowArray:Array = loadedData[i].split(",");
loadedData[i] = {"SelectAgreement":rowArray[0],"KSLTPROF0057":rowArray[1] .........};
}
loadedData.shift();
myGrid.columns = ["SelectAgreement", "KSLTPROF0057", ......];
import fl.data.DataProvider;
import fl.controls.dataGridClasses.DataGridColumn;
myGrid.dataProvider = new DataProvider(loadedData);
A DataGrid always shows all objects in its dataProvider, so to hide rows, you need to hide the data objects. Some classes that work as dataProviders have this functionality built in that makes this really easy (Any Class that implements IList can be operate as a dataProvider), however fl.data.DataProvider is not one of those classes.
So I will provide answers using both, if you can, I highly recommend using mx.collections.ArrayCollection over fl.data.DataProvider.
Section 1: fl.data.DataProvider
For this I'm assuming that your loadedData array is a class property, not declared in a function.
function agreement(event:Event):void
{
//your existing code here
var dataProvider:DataProvider = MyGrid.dataProvider as DataProvider;//recover the dataprovider
dataProvider.removeAll();//remove all rows
for (var x:int = 0; x<loadedData.length; x++)
{
if (loadedData[x] == "SELECTION MATCH") //insert here your selection criteria
{
dataProvider.addItem(loadedData[x]); //add it back into the dataProvider
}
}
}
function resetFilter():void
{
var dataProvider:DataProvider = MyGrid.dataProvider as DataProvider;//recover the dataprovider
dataProvider.removeAll(); //prevent duplication
dataProvider.addItems(loadedData);//reload all rows
}
Section 2: mx.collections.ArrayCollection
My reasoning for recommending this is because ArrayCollection already has the functions to do this without the risk of data being lost by objects losing scope, it also reduces the amount of code/operations you need to do. To do this we use ArrayCollection.filterFunction & ArrayCollection.refresh() to filter the "visible array" without changing the source.
private var dataProvider:ArrayCollection = new ArrayCollection(loadedData);
MyGrid.dataProvider = dataProvider;
function agreement(event:Event):void
{
//your existing code here
dataProvider.filterFunction = myFilterFunction;//use my filter
dataProvider.refresh();//refresh the visible list using new filter/sort
}
function resetFilter():void
{
dataProvider.filterFunction = null;//clear filter
dataProvider.refresh();//refresh the visible list using new filter/sort
}
function myFilterFunction(item:Object):Boolean
{
if (item == "SELECTION MATCH") return true;//insert your selection criteria here
else return false;
}
the filterFunction accepts a function and uses it to test each object in the ArrayCollection, the function has to return a Boolean, true for "Yes, display this object" and false for "Do not diplay".

Reverse engineering - Flash app

I have that code:
private function handleFlashVarsXmlLoaded(event:Event) : void
{
var secondsplit:String = null;
var item:Array = null;
var string:* = XML(String(event.target.data));
var notsplited:* = string.vars_CDATA; //what is .vars_CDATA?
var splitted:* = notsplitted.split("&");
var datacontainer:Object = {};
var index:Number = 0;
item = secondsplit.split("=");
datacontainer[item[0]] = item[1];
this.parseFlashVars(datacontainer); // go next
return;
}
That function is loaded when URLLoader is loaded.
I think that this function parse a XML file to string(fe. param1=arg1&param2=arg2), then split it by "&" and then by "=" and add data to datacontainer by
datacontainer["param1"] = "arg1"
But how should the XML file look like and what is string.vars_CDATA
I think, vars_CDATA is just a name of XML field, becourse variable named "string" is contains whole XML. So var "notsplited" contains a String-typed data of this field (I think so, becourse of the line "var splitted:* = notsplitted.split("&");", which splits String to Array).

string to instance name in action script 3

i'm having some problems with as3
var eventChildren:XMLList = eventInput.channel.children();
var nr:Number;
nr=0;
for each (var eventInfo:XML in eventChildren) {
nr++;
trace(eventInfo.title);
var ev="ev"+String(nr);
var titl="title"+String(nr);
trace(ev);
trace(titl);
var newEV:Object = Object(ev);
var newTITL:Object = Object(titl);
trace(newEV);
trace(newTITL);
newEV.newTITL.text=eventInfo.title;
}
}
this is my code, i'm trying to set the title value for every child instance of eventChild,
as i am new to action script in general, and action script 3 in particular i don't really know what i'm doing wrong here. I'm trying to set the text for ev1.title1, ev2.title2, etc. from values in eventChildren like this : first child, sets ev1.title1, second ev2.title2 and so on. Any ideas on what i should change in the code or where to look for some information ?
edit : thank you for the help, both answers took me to the right solution :
for each (var eventInfo:XML in eventChildren) {
nr++;
trace(eventInfo.title);
var ev="ev"+String(nr);
var titl="title"+String(nr);
//trace(ev);
//trace(titl);
var oTitle:Object = {}; // create object for the field titleXX
oTitle[titl] = {text:eventInfo.title}; // create and assign the field text to a new object
allFields[ev] = oTitle; // assign the title object to the field evXX
}
ev1.title1.text=allFields.ev1.title1.text;
ev2.title2.text=allFields.ev2.title2.text;
ev3.title3.text = allFields.ev3.title3.text;
ev4.title4.text=allFields.ev4.title4.text;
ev and titl are Strings and not Object, there is no eval in as3 so you will not be able to create a new variable based on a string name .But you can create a new Object that will have a field based on your ev string:
var o:Object={};
o[ev]="....";
So if ev is equal to the string "ev1" you will have an object with a field named ev1 => o.ev1=...
For the title you can do the same create a new Object that will have a field based on titl string:
var o:Object={};
o[titl]="...";
So if titl is equal to the string "title1" you will have an object with a field named title1 => o.title1=...
Same thing for the text you have to create an Object to hold the text field.
Mixing all this infos you end up with:
var eventChildren:XMLList = eventInput.channel.children();
var nr:Number=0;
var AllFields:Object={};
for each (var eventInfo:XML in eventChildren) {
nr++;
trace(eventInfo.title);
var ev="ev"+String(nr);
var titl="title"+String(nr);
trace(ev);
trace(titl);
var oTitle:Object = {}; // create object for the field titleXX
oTitle[titl] = {text:eventInfo.title}; // create and assign the field text to a new object
allFields[ev] = oTitle; // assign the title object to the field evXX
}
// then you can have access to all your field within the object allFields
trace(allFields.ev1.title1.text)
trace(allFields.ev2.title2.text)
See also this question for object notation
You can create the variable name using 'this':
this['mystring'] = new Object();
this.mystring.title = 'mytitle';
If you're doing this inside a class, the class has to be dynamic to allow for new members:
dynamic public class MyClass extends MovieClip {
public function MyClass() {
this['mystring'] = new Object();
this.mystring.title = 'mytitle';
}
}
If your class is not dynamic, you can still do this but must continue to use array notation rather than dot notation:
public class MyClass extends MovieClip { // not dynamic
public function MyClass() {
this['mystring'] = new Object();
this['mystring'].title = 'mytitle';
}
}

How to know what class is referenced by a Class object?

We have the Class object (an object that reference a Class) so you can create objects from that Class object:
var classObject:Class = package.to.class.AClass;
var objectFromClass:AClass = new classObject();
Now, I want to know what object is referenced by classObject. For example:
function Creator(classObject:Class):AClass
{
// here I want to know what class is referenced by classObject
return new classObject();
}
var classObject:Class = package.to.class.AClass;
var objectFromClass:AClass = Creator(classObject);
This works, but what if I pass a Class object that do not reference to AClass? I want to know if this happends and make somthing about it.
--- EDIT ---
Searching I found this function
flash.utils.getQualifiedClassName(value:*):String
This function returns the name of the class, for example:
var name:String = '';
// name = ''
name = flash.utils.getQualifiedClassName(package.to.class.AClass);
// name = 'AClass'
name = ''
// name = ''
var anInstance:AClass = new AClass();
name = flash.utils.getQualifiedClassName(anInstance);
// name = 'AClass'
So, all I have to do is to compare the results of that function:
function Creator(classObject:Class):AClass
{
var anInstance:AClass = new AClass();
var className:String = flash.utils.getQualifiedClassName(anInstance);
var classObjectName:String = flash.utils.getQualifiedClassName(classObject);
// here className and classObjectName are 'AClass' :)
if (className != classObjectName)
throw new Error('The classes are different');
return new classObject();
}
var classObject:Class = package.to.class.AClass;
var objectFromClass:AClass = Creator(classObject);
--- EDIT 2 ---
Another method is to use the constructor property of the Object class:
function Creator(classObject:Class):AClass
{
var tempInstance:AClass = new AClass();
var tempClassObject:Class = Object(tempInstance).constructor;
if (classObject != tempClassObject)
throw new Error('The classes are different');
return new classObject();
}
I found that the most simplest (not know if it's the fastest) way to accomplish this task is in the next example:
function Creator(classObject:Class):AClass
{
var anInstance:Object = new classObject() as AClass;
if (anInstance == null)
throw new Error('The classes are different');
return new classObject(); // or return anInstance as AClass;
}
This also works if AClass is an Interface.