+ Start a Discussion
MattLMattL 

Flex AsyncResponders: How to Wait For All Data

Code:
<—xml version="1.0" encoding="utf-8"–>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
 xmlns:salesforce="com.salesforce.*"
 applicationComplete="login();">

<mx:DateFormatter id="dateform" formatString="MM"/>
<mx:NumberFormatter id="numform" precision="0"/>

<mx:Script>
 <![CDATA[
  import flash.external.ExternalInterface;
  import com.salesforce.results.QueryResult;
  import mx.collections.ArrayCollection;
  import com.salesforce.AsyncResponder;
  import com.salesforce.objects.LoginRequest;
  import mx.controls.dataGridClasses.DataGridColumn;
  private function login():void {
   apex.login( new LoginRequest({
    server_url : this.parameters.server_url,
    session_id : this.parameters.session_id,
    callback : new AsyncResponder(render)
    })
    );
  }
  private function render(result:Object):void {
   var currId:String = ExternalInterface.call("getID");
   apex.query("Select Amount, CloseDate, OwnerId from Opportunity where AccountId='{!Account.Id}' and Probability=100",
     new AsyncResponder(
     function (qr:QueryResult):void
     {
      var month:int = 0;
      var x:int = 0;
      var amt:Array = new Array(0,0,0,0,0,0,0,0,0,0,0,0,0);
      var name:Array = new Array(" "," "," "," "," "," "," "," "," "," "," "," "," ");
      var months:Array = new Array("0","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
      var ar:ArrayCollection = new ArrayCollection();
      values.dataProvider = ar;
      for(var j:int=0;j<qr.records.length;j++) {
       month=numform.format(dateform.format(qr.records[j].CloseDate));
       amt[month]+=qr.records[j].Amount;
       apex.query("Select Name from User where Id='"+qr.records[j].OwnerId+"'",
       new AsyncResponder(
       function (qr2:QueryResult):void
       {
        name[x]=qr2.records[0].Name;
        x++;
       },
       function (fault:Object):void {}
       ));
      }
      ar=createArray(months, amt, name, ar);
     },
     function (fault:Object):void {}
  ));
 }
 private function createArray(months:Array, amt:Array, name:Array, ar:ArrayCollection):ArrayCollection {
  for(var i:int=1;i<13;i++)
  {
   ar.addItem( {Month:months[i], Amount:amt[i], Name:name[i]});
  }
  return(ar);
 }
 ]]>
</mx:Script>

<salesforce:Connection id="apex" />
 <mx:ColumnChart x="118" y="46" id="values">
  <mx:series>
   <mx:ColumnSeries displayName="Opp Amounts" yField="Amount"/>
   <mx:ColumnSeries displayName="Owner" yField="Owner"/>
  </mx:series>
 </mx:ColumnChart>
 <mx:Legend dataProvider="{values}"/>
 
</mx:Application>

I'm learning how to code simple Flex graphs, and I'm trying to push all my information into the ArrayCollection ar. The problem is that, regardless of what method I try, I'll put a breakpoint on the line return(ar) and a breakpoint on the line x++ under my second AsynchResponder. Inevitably, the return(ar) function will activate PRIOR to the breakpoint for x++, which means none of my names are initialized before the ArrayCollection is created. How does one 'wait' for all the data to be returned?
 


Message Edited by MattL on 01-28-2008 11:38 AM
Ron HessRon Hess
first step is to use the relationship query feature of SOQL to get the owner names in the first query, no need to loop and query on each record just to get the owner name. your code will become much simpler.

here is a simple query that gets the opp data AND the owner name at the same time.


Select Amount, CloseDate, OwnerId , owner.name, owner.firstname , owner.lastname from Opportunity

now you can restructure your code to only use one query and one responder to format the data for the resulting array.
MattLMattL
Thanks for the tip, Rob. Worked like a charm.

Got another question though. I'm trying to create Series elements on the ColumnChart, so each column stacks up to the total sales for that month. Each series element would represent the amount that sales person sold for that month. My aggregation code seems to work on par, but the chart creation keeps falling apart. Could anyone lend any insight into this?

Code:
<—xml version="1.0" encoding="utf-8"–>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
 xmlns:salesforce="com.salesforce.*"
 applicationComplete="login();">

<mx:DateFormatter id="dateform" formatString="MM"/>
<mx:NumberFormatter id="numform" precision="0"/>
<mx:Script>
 <![CDATA[
  import mx.charts.series.ColumnSeries;
  import flash.external.ExternalInterface;
  import com.salesforce.results.QueryResult;
  import mx.collections.ArrayCollection;
  import com.salesforce.AsyncResponder;
  import com.salesforce.objects.LoginRequest;
  import mx.controls.dataGridClasses.DataGridColumn;
  import mx.controls.Alert;
  
  [Bindable]
  private var ar:ArrayCollection = new ArrayCollection();
  private var name1:ArrayCollection = new ArrayCollection();
  
  private function login():void {
   apex.login( new LoginRequest({
    server_url : this.parameters.server_url,
    session_id : this.parameters.session_id,
    callback : new AsyncResponder(render)
    })
    );
  }
  private function render(result:Object):void {
   var currId:String = ExternalInterface.call("getID");
   apex.query("Select Amount, CloseDate, OwnerId, owner.name, owner.firstname, owner.lastname from Opportunity where AccountId='{!Account.Id}' and Probability=100",
     new AsyncResponder(
     function (qr:QueryResult):void
     {
      var month:int = 0;
      var amt:Array = new Array(0,0,0,0,0,0,0,0,0,0,0,0,0);
      var months:Array = new Array("0","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
      for(var h:int=0;h<13;h++)
      {
       name1.addItem( {Name:"", Amount:""} );
      }
      for(var j:int=0;j<qr.records.length;j++) {
       month=numform.format(dateform.format(qr.records[j].CloseDate));
       amt[month]+=qr.records[j].Amount;
       for(var k:int=0;k<name1.length;k++) {
        if(name1[k].Name==qr.records[j].Owner.Name)
        {
         name1[k].Amount+=qr.records[j].Amount;
        }
        else
        {
         name1.removeItemAt(month);
         name1.addItemAt( {Name:qr.records[j].Owner.Name, Amount:qr.records[j].Amount}, month );
        }
       }
      }
    for(var i:int=1;i<13;i++)
    {
     var temp:Object = name1.getItemAt(i);
     ar.addItem( {Month:months[i], Name:temp.Name, Amount:temp.Amount});
     for(var x:int=0;x<ar.length;x++)
     {
      var series:ColumnSeries = new ColumnSeries();
      series.xField = "Name";
      series.yField = "Amount";
      values.addChild(series);
     }
    }
     },
     function (fault:Object):void {}
  ));
 }
 ]]>
</mx:Script>

<salesforce:Connection id="apex" />
 <mx:ColumnChart x="125" y="44" id="values" type="100%" showDataTips="true" dataProvider="{ar}">
  <mx:horizontalAxis>
   <mx:CategoryAxis
    dataProvider="{ar}"
    categoryField="Month"
   />
  </mx:horizontalAxis>
  <mx:verticalAxis>
   <mx:CategoryAxis
    dataProvider="{name1}"
    categoryField="Amount"
   />
  </mx:verticalAxis>
 </mx:ColumnChart>
 <mx:Legend dataProvider="{values}"/>
</mx:Application>

 



raj78raj78

In your code below, you are using Account.Id to fetch the data related to this field. How are you able to access the Account.ID from the flex control? I'm trying to access the current record's ID but unable to.

 

Your help in this will be highly appreciated.

 

Thanks 

nitesurfernitesurfer

Why does the owner.name work within a query, but not within a formula?

 

David