Ok, so time for yet another "duh" moment in my Flex learning. Let me describe the situation I ran into a few days ago. I was working with a ColdFusion Component method that returned an array of objects. This array was being used in a datagrid. So far so good.
One of the things I wanted to do was make it so that when you selected an item from the datagrid, a second datagrid would be populated with a value from the selected item in the first datagrid. My initial array of objects contained a field, typicalsongs, that was also an array.
So here is where things got weird. At runtime when I clicked on an item in the first datagrid, I got the following error:
Variable Typical Song 1 for Station 1 is not defined
So this was really confusing. "Typical Song 1" was the literal first value in the array that should have been loaded into the second datagrid.
It didn't make any sense (and to defend my newbie-status, it confused a few experts as well). While I was trying to figure this out, I reminded myself that I needed to eventually added a DataGridColumn so I can provide a nice label.
Then it hit me. I was trying to load an array of simple values (strings) to the DataGrid. However, DataGrids want arrays of objects. That's where the grid gets the column labels in the first place.
So I'm not sure this is the best solution, but I fixed this in the Flex application. I tend to think I should keep my remote services more generalized and now build them just one for one client. Anyway, I used this code to handle the "rewriting" of the data:
private function loadSongs():void {
var currItem:Object = stationlistDG.selectedItem;
//The datagrid needs an "object", not a simple list
//I'm fixing it here as I feel that the web service is "right"
var newSongArray:Array = new Array();
for(var i:int=0; i < currItem.TYPICALSONGS.length; i++) {
var newSong:Object = new Object;
//matching case of stuff returned from CF
newSong.SONG = currItem.TYPICALSONGS[i];
newSongArray[newSongArray.length] = newSong;
}
songlistDG.dataProvider=newSongArray;
}
I could probably do this using the result handler of the initial call. My initial dataset is pretty small (and is guaranteed to be small) so that may make more sense.
Any other opinions?
Archived Comments
Hi Ray,
Wouldn't you want want to return an array of Value Objects paired to flash value objects? Thus avoiding the conversion step in flex?
I don't use VOs yet. I know I need to. I'm just not there yet in my development. Know what I mean?
I'd create a Station class and a Song class. In the Station class add a public bindable property songList:Array. In your Web Service call result handler I'd loop over the results and create an array of Stations where each Station's songList would hold an array of Song objects.
This feels a little redundant and it's a bit more work up front but (at least to me) it feels cleaner.
Why not use drop downs? They are pretty easy to populate.
Cheers,
Teddy
Exactly,
Ray, try to define a list like this
<mx:List dataProvider="{ stationlistDG.selectedItem.TYPICALSONGS }"/>
it should work.
Um, because I'm an idiot. Thanks for pointing this out. (The list, not the idiot part. ;)
Ray:
I'm curious about the comment you placed in the code "I'm fixing it here as I feel that the web service is "right"
Why not do the work of creating an Array of Song objects for each Station object in the CFC? I know that if you create a large number (hundreds) of objects in CF and pass that many to Flex there can be a time drag, but you state your dataset is guaranteed to be small.
By leveraging the power of the CFC, your Flex code would be much cleaner. Also if you wanted to expand in the future what information you include about the station's typical songs (song artist, song genre, etc) you can easily do that in the CFC and not have to change much in the Flex code (except how you display the additional data).
Anyway, perhaps I'm not following your logic for doing the work of creating the Array of Song objects in Flex instead of in the CFC.