I have created a PHP service in Flex Mobile and binded the result with a List. I want to sort the records from the service based on some calculation on data fields. So, is it possible to perform operations on the resultset from the PHP service ?
Detailed question:
I have created the php service through the built in tool in Flash Builder 4.6. I also had bind the service with a List in my view. (Again using GUI controls). Now I want to rearrange the items in the list based on distance from the current location and coordinates from the rows returned by the service. So the approach I was thinking was to, get the content from the service. Extract lat,lon and calculate the distance. Then update the list again.
I tried the following line in a function:
getAllplacesResult.lastResult[1].lon // lon is a column in the table.
But it returns a blank. Is their a more sane or easier way to do this ?
The better way is to assign it on an Arraycollection and manipulate data from there.
<mx:ArrayCollection id="myAC" source="{ArrayUtil.toArray(myRO.getAllplacesResult.lastResult)}" />
Make sure you bind myAC to your List.
Sort it the way you want to:
var collection:ArrayCollection = new ArrayCollection();
var s:Sort = new Sort();
s.fields = [new SortField("lat"), new SortField("lon")];
s.compareFunction = myCompareFunction;
collection.sort = s;
collection.refresh();
private function myCompareFunction(a:Object, b:Object, fields:Array = null):int {
...
}
Also, AS3 is 0 based index. 1 will actually give you the second row (or throw out of range exception)
Related
I am very new to programming in ActionScript3 and using SQLite. Currently I try to make an AIR application where it will handle from small to large dataset from excel, import into and calculate in AIR using ActionScript3 and stored the calculated data in SQLite.
Right now I have 2 question regarding using array to transfer data into SQLite
1. Is it possible to INSERT data or UPDATE data in SQLite without using looping?
In my AIR application, I have an object called DataInput in which have 62 variables/properties which will contain 62 different values from 62 columns in excel. I do know that if you create new instance of DataInput and push into array e.g arDataInput in loop, you can access each of the data in the array using arDataInput[i].variablename where i is the index of the array and variablename is the variables/properties of the object.
Obviously, right now I do actually using for loop to access the value of each cell in excel then calculate in AIR application before transfer the calculated data into SQLite, row by row within sql transaction.
Is there actually a way to transfer data in array into SQLite (either INSERT new row or UPDATE existing row) without using loop like INSERT INTO tblDataInputUW VALUES arDataInput given that each column name in SQLite table is the same as variables/properties of object within the array eg. SQLite table, tblDataInput have column name namePlat and array have variables/properties of arDataInput.namePlat?
2. Is it possible to split the data array i got from SQLite into multiple array without looping?
Right now, I use the following code to extract data from SQLite and stored as an array;
txtSQL = new String();
arData = new Array();
txtSQL = "SELECT namePlat, platLat, platLong FROM tblDataInput";
arData = getSQLData(txtSQL);
function getSQLData(text: String): Array
{
sqlCon.begin();
sqlStat = new SQLStatement();
sqlStat.sqlConnection = sqlCon;
sqlStat.text = text;
sqlStat.execute();
sqlCon.commit();
var result: SQLResult = new SQLResult();
var arData: Array = new Array();
result = sqlStat.getResult();
if (result != null)
{
arData = result.data;
}
return arData;
}
If my assumption are correct, I can access each of the value in arData by using arData[i].variablename where i is the index of the array and variablename is the table name within the SQLite table tblDataInput.
If there are way to split the data in arData into 3 different array e.g arNamePlat without using looping like arNamePlat = arData.variablename because I have many different chart to draw in my AIR application and each chart will have its own array to get value from.
Right now, I actually using different sql statement for different chart like;
txtSQL = new String();
arData = new Array();
txtSQL = "SELECT namePlat FROM tblDataInput";
arData = getSQLData(txtSQL);
dgNamePlat.dataProvider = new DataProvider(arData);
txtSQL = new String();
arData = new Array();
txtSQL = "SELECT platLat, platLong FROM tblDataInput";
arData = getSQLData(txtSQL);
dgPlatLatLong.dataProvider = new DataProvider(arData);
I use the same arData and txtSQL for each chart as I dont store the value anymore after the chart been drawn.
There are actually no restriction for me to just use for loop, I asking this question as I don't see any topic regarding on this question and as a self-learning programmer, I like to explore different way of coding and way to incorporate that knowledge into my projects.
The best way to send and receive data and do database stuff is through form submissions. AIR can POST regular form submissions like html pages but can also load a response. Regular serverside software like php handles the form submission, does whatever with the database, and returns data or simple success message.
The best way to handle data is to use XML (look into RESTful architecture for reasons why). PHP creates XML for the app. The xml gets loaded and should go into arrays of objects.
Here are some good links to get going on submitting data with forms and reading XML:
republic of code tutorials:
http://www.republicofcode.com/tutorials/flash/as3contactform/2.php
http://www.republicofcode.com/tutorials/flash/as3xml/
https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/URLRequest.html
https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/URLRequestMethod.html
When creating a user, entries are required in multiple tables. I am trying to create a transaction that creates a new entry into one table and then pass the new entityid into the parent table and so on. The error I am getting is
The transaction manager has disabled its support for remote/network
transactions. (Exception from HRESULT: 0x8004D024)
I believe this is caused by creating multiple connections within a single TransactionScope, but I am unsure on what the best/most efficient way of doing this is.
[OperationBehavior(TransactionScopeRequired = true)]
public int CreateUser(CreateUserData createData)
{
// Create a new family group and get the ID
var familyGroupId = createData.FamilyGroupId ?? CreateFamilyGroup();
// Create the APUser and get the Id
var apUserId = CreateAPUser(createData.UserId, familyGroupId);
// Create the institution user and get the Id
var institutionUserId = CreateInsUser(apUserId, createData.AlternateId, createData.InstitutionId);
// Create the investigator group user and return the Id
return AddUserToGroup(createData.InvestigatorGroupId, institutionUserId);
}
This is an example of one of the function calls, all the other ones follow the same format
public int CreateFamilyGroup(string familyGroupName)
{
var familyRepo = _FamilyRepo ?? new FamilyGroupRepository();
var familyGroup = new FamilyGroup() {CreationDate = DateTime.Now};
return familyRepo.AddFamilyGroup(familyGroup);
}
And the repository call for this is as follows
public int AddFamilyGroup(FamilyGroup familyGroup)
{
using (var context = new GameDbContext())
{
var newGroup = context.FamilyGroups.Add(familyGroup);
context.SaveChanges();
return newGroup.FamilyGroupId;
}
}
I believe this is caused by creating multiple connections within a single TransactionScope
Yes, that is the problem. It does not really matter how you avoid that as long you avoid it. A common thing to do is to have one connection and one EF context per WCF request. You need to find a way to pass that EF context along.
The method AddFamilyGroup illustrates a common anti-pattern with EF: You are using EF as a CRUD facility. It's supposed to me more like a live object graph connected to the database. The entire WCF request should share the same EF context. If you move in that direction the problem goes away.
I'm using Flash Builder 4.6 to create an app for a uni project. I have a custom Spark component, and I need to dynamically create a number of instances of that component at runtime depending on the number of XML elements returned via a PHP script.
That might be a bit confusing, so let me write the steps:
1) The application sends an HTTPService request to a PHP script hosted on the server.
2) The PHP accesses the SQL database and returns a series of XML data.
3) The ActionScript dynamically creates X instances of my custom Flex component, where X is the number of data in the XML.
Here's the code I've got so far (untidy because I'm trying to make it work):
ActionScript:
[Bindable]
public var holderArray:Array = new Array(100);
public function createMenu(e:MouseEvent):void {
var count:int = 0;
var curMenuItem:menuItemContainer = new menuItemContainer();
while (count < loadedMenu.length){
curMenuItem.itemName = loadedMenu.getItemAt(count).name;
curMenuItem.itemDesc = loadedMenu.getItemAt(count).description;
curMenuItem.itemPrice = numForm.format(loadedMenu.getItemAt(count).price);
curMenuItem.imageFile = loadedMenu.getItemAt(count).url;
//curMenuItem.y = count * 120
//menuItemGroup.addElement(curMenuItem);
holderArray[count] = curMenuItem;
count ++;
}
//testString = holderArray[1].itemName;
var count2:int = 0;
for each (var menuItem:menuItemContainer in holderArray){
menuItem.name = "menuItem" + count2;
menuItem.id = "menuItem" + count2;
//testString += menuItem.name;
menuItemGroup.addElement(menuItem);
count2++;
}
}
MXML:
<s:VGroup id="menuItemGroup" x="40" y="150">
</s:VGroup>
What seems to be happening with that code is that each of my three XML data that get returned are being used in instances of menuItemContainer, but when each one is added to menuItemGroup, it's overwriting the one that's already there. I'm not sure if the item is actually getting overwritten, or if the new item is just sitting atop the earlier ones, but if the latter is true I can't find a way to arrange the components. I've tried setting menuItem.y in the loop (as a function of count2), but to no avail.
Thanks in advance for any and all suggestions/answers.
Benjamin.
Put this line
var curMenuItem:menuItemContainer = new menuItemContainer();
inside your while loop. With your code as it is you are only creating one instance of menuItemContainer then continually changing the properties of that one menuItemContainer in your while loop. Instead you need to create a new, different instance of menuItemContainer with each iteration of the loop.
Here's some code,
k.Bind<IGame>().To<Game>().Named("A")
.WithConstructorArgument("ColorChoiceCount", 12);
iGame = k.Get<IGame>("A");
((Game)iGame).SelectedColor = new GameColor(System.Drawing.Color.Red);
iGame = k.Get<IGame>("A");
On the first iGame = k.Get<IGame>("A"); I get a new instance of Game.
Next line: I change one of it's properties.
Next line (iGame = k.Get<IGame>("A"); again) I get a new instance again.
What I would like is to be able to retrieve instances I've already used.
But I'm totally new to this kind of tools so I guess I'm missing something.
Thank you if you can help me.
You need to specify the lifetime of your object - by default the container will create a new instance.
The available methods are as follows:
InScope
InTransientScope
InThreadScope
InSingletonScope
InRequestScope
http://blog.bobcravens.com/2010/03/ninject-life-cycle-management-or-scoping/
You probably want a singleton (single instance of the game):
k.Bind<IGame>().To<Game>().InSingletonScope().Named("A")
.WithConstructorArgument("ColorChoiceCount", 12);
I have an AdvancedDataGrid with a HierarchicalCollectionView as its dataProvider. When I view the grid with the dataset I'm working with, and click the header of the column I wish to sort on, everything works perfectly. It sorts it hierarchically exactly how I would expect it to.
What I want to do now is have the grid already be sorted when it is shown to the user. Is there a way to do this programatically? I can't for the life of me figure out how to do this, and clearly it's possible since the AdvancedDataGrid has this built in.
Edit - BTW, I've tried this:
var myData:HierarchicalCollectionView = new HierarchicalCollectionView(theDataSource);
// Works fine using only the line above and clicking the header to sort.
// This is the part that I tried adding:
var sort:Sort = new Sort();
sort.fields = [new SortField("startDate")];
myData.sort = sort;
myData.refresh();
This appears to do something as far as sorting goes, but it doesn't sort it in the same way as clicking the column header. "startDate" is a property of an object in theDataSource by the way.
Looks like you want to sort dates. Sort can't do that out of the box. You have to use a compareFunction.
If your objects are of type Date it's quite easy:
var sortField:SortField = new SortField("startDate");
sortField.compareFunction = ObjectUtil.dateCompare;
In case your column contains dates as strings you'll have to parse them first (code example from http://blog.flexexamples.com/2007/08/12/sorting-date-columns-in-a-datagrid/):
private function date_sortCompareFunc(itemA:Object, itemB:Object):int
{
/* Date.parse() returns an int, but
ObjectUtil.dateCompare() expects two
Date objects, so convert String to
int to Date. */
var dateA:Date = new Date(Date.parse(itemA));
var dateB:Date = new Date(Date.parse(itemB));
return ObjectUtil.dateCompare(dateA, dateB);
}
var sortField:SortField = new SortField("startDate");
sortField.compareFunction = date_sortCompareFunc;
Then just use the sortField like you did in your example. That should work fine.
You can create a new advanced data grid sort event and dispatch it on the grid after the hierarchical data is set on it (unfortunately I've had to use a callLater to give the grid time to deal with the collection internally it seems assignments to the dataProvider of the ADG are sometimes asynchronous)
var advancedDataGridEvent : AdvancedDataGridEvent = new AdvancedDataGridEvent(AdvancedDataGridEvent.SORT, false, true);
advancedDataGridEvent.columnIndex = columnIndex;
advancedDataGridEvent.dataField = dataField;
dispatchEvent(advancedDataGridEvent);
This code is from an extension of ADG so you would want the dispatchEvent to actually be on your instance of the grid if you're not creating an extension.
Also a note from the code:
//setting sortDescending=true on a column does not work as expected. so, until a solution
//is found, this works just as well. the event that is dispatch just tells the column
//to reset. so, one resorts ascending (the default), while a second resorts descending.
//however, this second is only dispatched if defaultSortDesc is true on the grid.
if (defaultSortDesc)
{
dispatchEvent(advancedDataGridEvent);
}
It dispatches the event twice to flip the sort.