I have a component where I define an attribute (forcasts) as an object array. In this case the Saleforce object is named “Forecast_Actuals__c”. These are child records under each Opportunity. The attribute definition is:

<aura:attribute name="forecasts" type="Forecast_Actuals__c[]" />

I have a helper function that calls the apex controller and sets up the callback. I am expecting a list (array) of records to be returned from the Apex controller.

In the Apex controller, after I make the SOQL call I check the list length of my return variable using system.debug (system.debug(FC_List.siz());) and I get a value of 6, which is correct.

In the callback function, I load the response into my forecast variable:

var forecasts = component.get("v.forecasts");

Then I check the array length in my helper and it is 1 instead of the 6 I was expecting. If I use console.log(JSON.stringify(forecasts) it prints all of the data from the SOQL call. Again, the array size is 1, so all of the data I returned from the Apex controller was loaded into one element of my variable in my helper controller.

How should I be handling the response in the callback in order to load the record data into an array?

Here's the Component:

<aura:component controller="ForecastController" implements="force:lightningQuickAction,flexipage:availableForAllPageTypes,force:hasRecordId">
    <aura:handler name="init" action="{!c.doInit}" value="{!this}"/>

    <aura:attribute name="forecastdate" type="Date" />
    <aura:attribute name="recordId" type="Id" />
    <!-- 'forecasts' is an array of records from the database -->
    <aura:attribute name="forecasts" type="Forecast_Actuals__c[]" />
    <aura:attribute name="updatedForecast" type="Forecast_Actuals__c[]"/>
    <aura:attribute name="previousActuals" type="Forecast_Actuals__c[]"/>

    <lightning:card iconName="action:new_event">
        <aura:set attribute="title">
            12 Month Forecast, PMXXXX
            <div class="demo-only demo-only--sizing slds-grid slds-wrap">
                <div class="slds-size_1-of-2">
                    <lightning:input type="Date" label="Start Date (mm/dd/yyyy)" name="startdate" onchange="{!c.dateChanged}" value="{!v.forecastdate}" />
        <c:forecastMonth />

Here's the Apex Controller:

public with sharing class ForecastController {

    public static List<Forecast_Actuals__c> getForecastActuals(Id recordId, String queryStartDate, String queryStopDate){
        List<Forecast_Actuals__c> FC_List;
        Date StartMonth;
        Date StopMonth;

        StartMonth = Date.valueOf(queryStartDate);
        StopMonth = Date.valueOf(queryStopDate);

        //FC_List = [Select Name from Forecast_actuals__c where Opportunity__c = :recordId];
        FC_List = [select name, FA_External_ID__c, Opportunity__c, x1st_Day_of_Forecast_Month__c, Forecast_Quantity_for_Month__c, Forecast_Sell_Price_for_Month__c from Forecast_Actuals__c where (Opportunity__c =: recordId) AND (x1st_Day_of_Forecast_Month__c >= :StartMonth) AND ( x1st_Day_of_Forecast_Month__c <= :StopMonth) order by x1st_Day_of_Forecast_Month__c ASC];

        return FC_List;

And here's the helper controller with the callback:

    getRecords : function(component, recordId, forecastdate) {
        var queryStartDate = (parseInt(forecastdate.slice(0,4))-1).toString() + forecastdate.slice(4,10);
        var queryStopDate = (parseInt(forecastdate.slice(0,4))+1).toString() + forecastdate.slice(4,10);
        var action = component.get("c.getForecastActuals");
            "queryStartDate": queryStartDate,
            "queryStopDate": queryStopDate
        action.setCallback(this, function(response){
            var state = response.getState();
            if (state === "SUCCESS") {
                var forecasts = component.get("v.forecasts");
                console.log("Length of forcast from callback: " + forecasts.length)
                //clear array of previous data
                forecasts = []; 
                //load array with new data
                console.log("Length of forcast from callback after push: " + forecasts.length)
                component.set("v.forecasts", forecasts);
                //console.log("Forecast List: " + JSON.stringify(forecasts));

        //Invoke the action
  • why are you creating a js array and then pushing the reponse from the array, why aren you not using component.set("v.forecasts",response.getReturnValue());? – Rao Sep 28 '17 at 23:02
  • Rao - I need to do some other operations on the data in my controller, which I have'nt implemented yet. Thanks, Mike – m. Gann Sep 28 '17 at 23:53

Push pushes an element on to the Array. An Array may contain another Array, so you've basically made something like this:

[ { Forecast1 }, [ { Forecast2, Forecast3, ... } ] ]

In other words, you now have an Array inside an Array.

Instead, if you want to add items from a list, you should use concat:

forecasts = forecasts.concat(response.getReturnValue());

Note that concat returns a new Array that contains both of the original arrays, hence the assignment back into the forecasts variable.

  • This was the answer! I'm new to this and every little nugget helps, thank you very much - Mike – m. Gann Sep 29 '17 at 13:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.