I've got content coming into my application using a query and an ArrayCollection. I know how to display the content into a DataGrid by using the dataProvider propriety, but I'd like to use TextInput components and drop the DataGrid altogether.
Does anyone have any examples or information on how I would go about doing this?
Thanks!
Thank you for the insight - invertedSpear
I'm still having a problem all that displays is [object,object]
Here is a bit of my code.
[Bindable]
private var acCon:ArrayCollection;
private function reData():void //RETRIEVE DATA
{
var stmt:SQLStatement = new SQLStatement();
stmt.sqlConnection = sqlConn;
stmt.text = "SELECT * FROM person";
stmt.execute();
var result:SQLResult = stmt.getResult();
acCon = new ArrayCollection(result.data);
}
<mx:Repeater id="repeater1" dataProvider="{acCon}">
<mx:Label id="Label1" text="{repeater1.currentItem}"/>
</mx:Repeater>
Any thoughts?
Your question is not clear. The format of your query result and exactly how you are wanting to display them make a difference in this.
Things you need to do no matter what the format.
1) make sure you have a bindable variable to store your query result in:
[Bindable] public var myArrayCollection:ArrayCollection = new ArrayCollection();
2) assign you query result to this.
3) probably going to need to use a loop or a repeater based on your results length, not sure what your result looks like so you will have to figure this out.
4) assign the values to text boxes.
<mx:Text text="{myArrayCollection.FieldName}">
This answer is my best guess to what your question is. Please edit your question to make it more clear if this answer doesn't work for you.
Looking at your code example that's now up I am guessing you are very close, your repeater is kind of like your query result. Current item is like a row of your query. you probably just need to add the field name to it. So Maybe:
<mx:Label id="Label1" text="{repeater1.currentItem.LastName}"/>
Related
Simple to understand problem, hoping for similarly easy solution:
When I type in my search query, I sometimes get the "Error #1009 Cannot access a property or method of a null object reference" on the dataField = new ArrayCollection(result.data); line.
AS3:
private function getSearch():void
{
//status = "Loading data";
selectStmt = new SQLStatement();
selectStmt.sqlConnection = conn;
var sql:String = "SELECT [Index], Title, CAST(Picture AS ByteArray) AS Picture FROM Data WHERE Title LIKE #searchTarget";
selectStmt.parameters["#searchTarget"] = "%" + searchTarget + "%";
selectStmt.text = sql;
selectStmt.addEventListener(SQLEvent.RESULT, selectResult2);
selectStmt.addEventListener(SQLErrorEvent.ERROR, selectError);
selectStmt.execute();
targetRecordId = pngIndex;
}
private function selectResult2(event:SQLEvent):void
{
//status = "Data loaded";
selectStmt.removeEventListener(SQLEvent.RESULT, selectResult);
selectStmt.removeEventListener(SQLErrorEvent.ERROR, selectError);
var result:SQLResult = selectStmt.getResult();
dataField = new ArrayCollection(result.data);
if (result.data != null) {
pngIndex = result.data.Index;
pngTitle = result.data.Title;
pngByteArray = result.data.Picture;
targetRecordId = pngIndex;
}
}
mxml:
<s:List id="myList"
x="0" y="40"
width="100%" height="100%"
labelField="Title"
dataProvider="{dataField}"
change="myList_changeHandler(event)"
>
</s:List>
Things I've tried (including the permutations of these solutions):
1) Moving the error code inside the SelectResult2 method
2) Adding an if (result.data == null) method
3) Using Array instead of ArrayCollection (I found someone who found that this worked for their project on some forum somewhere)
4) Adding a timer function to try and limit how often the db will get searched. (although I think this was the best solution, I think I will have to try this one again)
Note, the error occurs, from what I can tell, largely as a result of entering search characters too quickly
Thank you for your help.
1. Use Responders
You're using the same event handler function for each call to the database. Hence when the function gets executed it might have lost the reference to its original statement (because a new call was initiated in the meantime). That's why you get those nullpointers on the result object.
So ditch the event listeners and use a Responder instead, like so:
var stmt:SQLStatement = new SQLStatement();
stmt.sqlConnection = connection;
stmt.text = query;
var resp:Responder = new Responder(onResult, onFail);
stmt.execute(-1, resp);
The 'onResult' function will take a SQLResult object as a single argument and you no laonger have to reference the original statement to get that result.
2. Delay
Use a Timer, yes. But don't use it to make the database call on an interval. You wouldn't know when to stop making those calls, would you? Use it to detect whether the user is still typing or not: when it takes longer than - say - 300ms. for one KeyboardEvent.KEY_UP to come after another, then fire the call to the database. Once.
3. Use a threshold
Don't start querying with just one letter. Use a threshold of at least 2-3 characters. You won't get any relevant suggestions with one character anyway. How high the threshold should be, depends on the size of the collection to search.
4. Filter an ArrayCollection
Ignore all of the above. An easier solution might be to just load all the records you want to search into an ArrayCollection and use filterFunction to show only the records that match a certain String. This method will do fine as long as the collection is not gigantic (like tens of thousands of records) and is way faster to implement.
first, how about
if(result == null)
return;
Also, the timer is a good idea, usually about half a second, that way your database isn't being hammered while the user is typing.
private var timer:Timer = new Timer(500, 1);
protected function textChangeHandler():void{
timer.reset();
timer.addEventListener(TimerEvent.Timer, getSearch);//Could be moved to a creation complete
timer.start();
}
error handle and remove/add events as appropriate. You could also disable the search until the last one has completed, which in combination with the timer shouldn't be intrusive to the user.
I#m looking for a solution to sort all grouped colums in advancedDatagrid. It should be the same behavior like clicking in a columns head.
Please note, i'm not looking for a solution to sort the fields IN a the grouping. There is working solution named compareFunction.
But I'm not able to sort the two rows in my picture by column "Einnahmen". Sorry for the german word.
Do you have an Idea?
Thank you
Frank
If you're looking to start the application with sorted columns, you need to simulate a header click upon creation/dateprovider update.
Try this:
<mx:AdvancedDataGrid id="adg"
updateComplete="adg.dispatchEvent(new AdvancedDataGridEvent(AdvancedDataGridEvent.HEADER_RELEASE, false, true, 3, 'Einnahmen'))">
<mx:columns>
...
<mx:AdvancedDataGridColumn dataField="Einnahmen" sortDescending="true" />
</mx:columns>
</mx:AdvancedDataGrid>
I haven't tried this for grouped collections but let me know how this works.
EDIT:
I didn't know you were building your dataProvider through ActionScript. You should still be able to run the Sort on your collection after you've finished putting it together though.
Another option would be to extend the AdvancedDataGrid component and override the set dataProvider method to sort the data as soon as you bind it. Here's an example another developer provided (source) for the Tree control, but the same concept could probably be used on the AdvancedDataGrid.
Original answer:
Assuming you're just trying to sort the top level "Einnahmen" values (which it looks like you are from your screenshot), I would manually sort your dataProvider after data is returned from whatever service you're using to get your data.
Here's a very basic example of manually sorting your collection.
[Bindable] public var MyDataList:ArrayCollection;
private var einnahmenSortField:SortField = new SortField("Einnahmen", true, false);
private var theSort:Sort = new Sort();
// Called after data is returned from the remote service call to sort the data
public function SetMyDataList(returnedList:ArrayCollection):void
{
MyDataList = returnedList;
if (theSort == null)
{
theSort = new Sort();
theSort.fields = [einnahmenSortField];
}
MyDataList.sort = this.theSort;
MyDataList.refresh();
}
To convert it to HierarchicalData for use in your AdvancedDataGrid, just create a new instance of HierarchicalData and assign it to your AdvancedDataGrid like this:
var hd:HierarchicalData = new HierarchicalData(myDataList);
hd.childrenField = "MyChildField";
myAdvancedDataGrid.dataProvider = hd;
Did you try to set the 'sortExpertMode="true"' in the AdvancedDataGrid tag? Please find the sample code below:
<mx:AdvancedDataGrid height="318"
id="dataSetsDG"
allowMultipleSelection="false"
folderClosedIcon="{null}"
folderOpenIcon="{null}"
defaultLeafIcon="{null}"
left="28"
top="162"
rowCount="11"
width="70%"
displayItemsExpanded="true"
sortExpertMode="true">
I used 'HierarchicalData' as the dataprovider for the AdvancedDataGrid.I also created the HierarchialData from the ArrayCollection, the sort order was maintained and it works like a charm.You can give it a try!
Please find the Actionscript code and a sample screenshot.
public function createHierarchialResultVO(results:ArrayCollection):ArrayCollection
{
[ArrayElementType("ResultsVO")]
var dpHierrarchy:ArrayCollection = new ArrayCollection();
for each(var result:Result in results)
{
var resultVO:ResultsVO= new ResultsVO();
resultVO.resultName = result.resultName;
resultVO.runDate = result.runDate.toString();
resultVO.type="header";
var childrens:ArrayCollection = new ArrayCollection();
for each(var processDetails:ProcessDetails in result.details)
{
var children:ResultsVO= new ResultsVO();
children.files =result.fileCount;
children.status=result.status;
children.type="result";
}
resultVO.children =children;
dpHierrarchy.addItem(resultVO);
}
return dpHierrarchy;
}
I have an SQL Statement which I want to read the name fields from an SQL database. the code:
public function getAllGiberish():void {
var stmt:SQLStatement = new SQLStatement();
stmt.sqlConnection = sqlConnection;
stmt.text = "SELECT name FROM test3";
stmt.execute();
l.dataProvider = new ArrayCollection(stmt.getResult().data);
}
This will pull the data from the db. However, in the list item it shows everything up as [object Object]. Upon debugging I can see that the data provider shows:
data[0] > name
data[1] > name
data[2] > name
Where the info that I want is the name within each data object.
How do I easily access this? It is a problem I keep coming across and would like to work it out once and for all!
Cheers
You want to set the labelField property on the list (Assuming Flex 3 here). By default it's looking for a field called "label" not "name". Also look at the dataField and labelFunction properties of the list object for some more advanced options.
The result of the query returns an array of Object instances, while you might expect String, with their keys equal to the column names that you select. You will either need to alias the "name" column to "label" in your query (as the List control uses this as the default labelField as Chris metioned), or you need to set the labelField or a labelFunction on the List control.
Note that you can also return typed objects instead of plain Object instances by setting the itemClass property on the statement.
You could write a label function:
private function list_labelFunction(item:Object):String {
return item.columnName;
}
And make sure that your List has a label function set:
<s:List id="myList" labelFunction="list_labelFunction"/>
That's how I did it anyway!
I have a UI component that, for various reasons, I have to construct programatically. The component is a table of radio buttons grouped by column.
Right now, I'm constructing the column groups like so:
private function createGroupsForItemList(items: XMLList): void {
for each (var item: XML in items) {
var rbGroup: RadioButtonGroup = new RadioButtonGroup();
groups[item.#level.toString()] = rbGroup;
}
}
I'm trying to associate the RadioButton instances with the column groups like so:
private function createValueControl(item: XML): UIComponent {
var control: RadioButton = new RadioButton();
control.label = "";
control.group = groups[item.#level.toString()];
control.addEventListener(Event.SELECT, updateSelection);
return control;
}
I can see in the debugger that the control has an association to the group:
control.group == groups[item.#level.toString()]
However, I can see equally that the group does not know anything about the control:
group.radioButtons.length == 0
I imagine that this is because the setter for group in RadioButton is a dumb setter; all it does is copy to the variable, which doesn't do the magic that groupName does. However, I can't seem to find the value I should use to set the RadioButton.groupName property correctly.
So, in short, I'm stumped on how to get these bits to talk to each other. How do I do this?
-- EDIT --
It turns out that I can have the groups created and associated simply by setting the groupName property, but I can't get at the group to set up a selection listener; the group is NULL immediately after the setting process, which means that the second line below throws the Flex equivalent of an NPE:
control.groupName = groupNameForLevel(item);
control.group.addEventListener(Event.SELECT, updateSelection);
First instinct is that this issue has to do with invalidateDisplayList and when and how that is called. Of course, since issues related to that function are behind a number of Flex's quirks, I may just be scapegoating.
This is not the answer to your question per se, but it seems like it might actually work as an alternate solution.
RadioButtonGroups will initialize based on a IFlexDisplayObject. This means that you can do something like:
var c:HBox = new HBox();
var rbg:RadioButtonGroup = new RadioButtonGroup( c );
// do stuff with rbg.
c.addChild( new RadioButton() );
The problem is that it may not be the most practical answer, but it has the decided benefit of being a workable solution.
Setting groupName should work.
All I can suggest is to step through the group() getter of the RadioButton component and see where exactly it is failing. Are you programmatically creating the group too? If that's the case, maybe it isn't initialized fully yet.
I am trying to find a way bind Grid view to a JSON.NET parsed Linq to Json object
simply am calling
JObject yrs = SearchData("");
then use one property to be bound to Grid view
GridView1.DataSource = yrs["businesses"].Children();
I cant find any resources for something like that
neither binding directly work nor using Children, and seems like I can not find it in the documentation.
appreciate your help
I think I just needed to sleep :)
this is how it should go, if someone need that ,
var bsn =from c in yrs["businesses"].Children()
select new { Title = (string)c["Title"] , Type = (string)c["Type"] };
GridView1.DataSource = bsn;
if there are better ways please advice