tags:

views:

971

answers:

5

Hi guys.

This is related to other question. But never mind it. I've fixed part of it.

I have a DataGrid, its data provider is a ArrayCollection, and i want it to parse all itens in it (Object Type) to a String.

For that I've done a "for each" loop, it manages to get the Object and its values, but if i have more that one object it only gets the last object, don't know why.


First i will show how these items are added to the ArrayCollection, that way you will understand the rest much easily.

In the Main Application i have the ArrayCollection:

<mx:ArrayCollection id="collection">

Then in other Component there is a Add Item Menu, and when you add a item:

private function fazerEncomenda():void
{
    var novoitem:Object;
    novoitem = new Object();
    novoitem.id = "consumivel"+getProdInfo.lastResult.consumivel.id;
    novoitem.tinteiroid = getProdInfo.lastResult.consumivel.id;
    novoitem.label = getProdInfo.lastResult.consumivel.nome;
    novoitem.ref = getProdInfo.lastResult.consumivel.refmarca;
    novoitem.marca = getProdInfo.lastResult.consumivel.marca;
    novoitem.genero = genero.text;
    novoitem.quantidade = quantidade.text;
    Application.application.collection.addItem(novoitem);
}

Then in another component the DataGrid as its dataProvider Binded to the ArrayCollection

<mx:DataGrid id="compras" x="0" y="0" width="556" dataProvider="{Application.application.collection}" editable="false">
     <mx:columns>
      <mx:DataGridColumn headerText="ID" dataField="tinteiroid" visible="false"/>
      <mx:DataGridColumn headerText="Nome" dataField="label" width="120" />
      <mx:DataGridColumn headerText="Ref" dataField="ref" width="100"/>
      <mx:DataGridColumn headerText="Marca" dataField="marca" width="100"/>
      <mx:DataGridColumn headerText="Género" dataField="genero" width="155"/>
      <mx:DataGridColumn headerText="Quantidade" dataField="quantidade" width="81"/>
     </mx:columns>
    </mx:DataGrid>

And when a Button is pressed the function to get all Objects and its values to an String.

And in this function its where it only gets the last item, in the ArrayCollection.

for each (novoitem in compras.dataProvider)
{
    finish += "TinteiroID:"+novoitem.tinteiroid+"#TinteiroLABEL:"+novoitem.label+"#TinteiroREF:"+novoitem.ref+"#TinteiroMARCA:"+novoitem.marca+"#TinteiroGENERO:"+novoitem.genero+"#TinteiroQUANTIDADE:"+novoitem.quantidade+"#FIMPROD#";
    trace(finish);
}

And of course the Vars used in the function:

private var finish:String;
private var novoitem:Object

As you see in the finish var i used += so it adds it self and the next object. Instead he adds null. And only one null event if there was 3 items before.

Don't know whats the problem with this loop.

Please Help. I'm loosing my mind here.

PS: Sorry for any bad English, its been 3 hours in this. And no progress.

EDIT: Missing Vars Declaration Added

+1  A: 

Have you tried ".source" property of your array collection? I'm not sure if for-each loops work on ArrayCollection objects.

e.g.,

for each(novoitem in compras.dataProvider.source) { ... }
Glenn
Yes I've tried to, forgot to mentioned. Same result.
Fábio Antunes
try assigning the dataprovider to a temporary ArrayCollection variable before the loop. Confirm the size. Then assign the ac.source to another variable. Confirm the size. Try to narrow down where the problem is happening.
Glenn
A: 

This is the trace(finish) output:

nullTinteiroID:1#TinteiroLABEL:HP CB335EE#TinteiroREF:CB335EE#TinteiroMARCA:HP#TinteiroGENERO:Tinteiro Preto Reciclado#TinteiroQUANTIDADE:23#FIMPROD#

Notice that it only as one Object with all its itens, and starts with null, where it should be the other itens before. Also notice that the outputted item is the last, 2 others are missing.

I think the problem is somewhere here finish +=

This would add to the var finish its own value and the next value for each item. Wich should result in something like this:

TinteiroID:1#TinteiroLABEL:HP CB335EE#TinteiroREF:CB335EE#TinteiroMARCA:HP#TinteiroGENERO:Tinteiro Preto Reciclado#TinteiroQUANTIDADE:23#FIMPROD#

TinteiroID:1#TinteiroLABEL:HP CB335EE#TinteiroREF:CB335EE#TinteiroMARCA:HP#TinteiroGENERO:Tinteiro Preto Reciclado#TinteiroQUANTIDADE:23#FIMPROD#

TinteiroID:1#TinteiroLABEL:HP CB335EE#TinteiroREF:CB335EE#TinteiroMARCA:HP#TinteiroGENERO:Tinteiro Preto Reciclado#TinteiroQUANTIDADE:23#FIMPROD#

With other values of course.


Could you help me to do this: for each(novoitem in compras.dataProvider.source)

In other way, to do it while the number of objects returned are less then Application.application.collection.length

Collection is the ID for my ArrayCollection.

Thanks for your help so far.

Fábio Antunes
+1  A: 

have you tried to just use a regular for loop

for (var i:int = 0; i < compras.dataProvider.length; i++) {

novoitem= compras.dataProvider[i];
trace(novoitem); // will output to the console during debugging. 
...
}

in any case you shouldn't be looping on the dataProvider you sould be looping on the Application.application.collection

AndrewB
compras.dataProvider.length won't work but Application.application.collection.length works pretty well.
Fábio Antunes
A: 

Guys i really want to thank you.

Thanks to your effort Glenn and AndrewB i did it. Once again thanks.

Now i will post the code so that someone with a similar problem can get some help.

Here goes the code to get the Objects and the Itens for each object inside a ArrayCollection.

[Bindable]
private var finish:String = "";
private var novoitem:Object
for (var i:int = 0; i <Application.application.collection.length; i++)
{
 novoitem = compras.dataProvider[i];
 finish = finish + "TinteiroID:"+novoitem.tinteiroid+"#TinteiroLABEL:"+novoitem.label+"#TinteiroREF:"+novoitem.ref+"#TinteiroMARCA:"+novoitem.marca+"#TinteiroGENERO:"+novoitem.genero+"#TinteiroQUANTIDADE:"+novoitem.quantidade+"#FIMPROD#";
 trace(finish);          
}

Thanks once again. I wanted to place both your awnsers as correct, but they aren't completely. So I've combined both to this code. And here it is.

I will be signing this answer as correct, but the credit its all yours. I wouldn't have it done if it weren't with you help.

EDIT This is the code I've used however take a look at the code that "CaspNZ" as posted. Its probably a better and lighter approach in performance.

Fábio Antunes
+1  A: 

An easier way to do all this (admittedly not with the labels you specified) is to just use ActionScript's built in ObjectUtil.toString method.

You would write something like this:

import mx.utils.ObjectUtil;

public function dumpObj():void {
    myTextField.text = ObjectUtil.toString(obj);
 }

This should pretty much print out every property of every multiple / nested object you have.

HOWEVER - you should make a fundamental change to your component if you want it to be reusable. You need a getter/setter for your collection. In the component, add this code:

[Bindable]
private var _myCollection:ArrayCollection;

public function set myCollection (data:ArrayCollection) : void {
    _myCollection = data;
}

public function get myCollection () : ArrayCollection {
    return _myCollection;
}

There are several other ways to do this - look it up if you need something different. In your datagrid, use the private ArrayCollection variable like this:

<mx:DataGrid id="compras" x="0" y="0" width="556" dataProvider="{_myCollection}" editable="false">
    <mx:columns>
            <mx:DataGridColumn headerText="ID" dataField="tinteiroid" visible="false"/>
...

In the main application, you can populate your component like this:

<kgtm:myComponent x="0" y="20" myCollection="{queryDataAC}"

And you name your ArrayCollection like this:

<mx:ArrayCollection id="queryDataAC">

in your top level Application code, you define the kgtm namespace, so you can use your custom component, like so:

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:kgtm="com.kgtm.*"

Then put your component in the folder corresponding to this namespace definition.

This all leads to the final object print utility - which you define on the component, as it is the only thing that should know about how to print out it's data.

Define a public function, and get it to print out the private ArrayCollection data, using ObjectUtil or your own method.

public var getLastQueryOutput () : String {

private var output:String = "";
private var len:int = _myCollection.length;
for (var i:int = 0; i <len; i++)   {
    output = output + 
    "TinteiroID:"+_myCollection[i].tinteiroid+
    "#TinteiroLABEL:"+_myCollection[i].label+
    "#TinteiroREF:"+_myCollection[i].ref+
    "#TinteiroMARCA:"+_myCollection[i].marca+
    "#TinteiroGENERO:"+_myCollection[i].genero+
    "#TinteiroQUANTIDADE:"+_myCollection[i].quantidade+
    "#FIMPROD#";

}
trace(output);

}

Hopefully this will help. If you name the object correctly as you are putting it into the ArrayCollection, you can again just use ObjectUtil as I stated at the top.

Casp - Check out more of my (and my colleagues) blog entries here

CaspNZ
That looks alike to what i did, i didn't post all the code, to don't discourage you guys to help me. This adds, binds the collection from .mxml file to another mxml file and between components. How ever no doubt that yours will work too.
Fábio Antunes
PS: Thats why i only include that add code of mine just to you guys, have a better understanding. And it Worked that way. I had loads of help. Thanks again to all of you.
Fábio Antunes
Glad it all worked out for you :-)
CaspNZ