7

I am trying to access the attribute which I am assigning the value in Helper, and calling the helper in Controller init, but while accessing the the same attribute in init, its returning undefined.

Here is my code

Helper

userName : function(component) {
    //loading user related data
    var action = component.get("c.getUserName");
    action.setCallback(this, function(response){
        var state = response.getState();
        if (state === "SUCCESS") {
            component.set("v.Name", response.getReturnValue());
           // alert('$$$' + component.get("v.Name"));

         }
    });
    $A.enqueueAction(action);   
},

Controller

doinit : function(component, event, helper) {

    helper.userName(component);
    //here its returning undefined 
    alert(component.get("v.Name"));
}

Component

<aura:handler name="init" value="{!this}" action="{!c.doinit}"/>

<aura:attribute name="Name" type="String" /> 
  • 3
    This is happening because of a well-known reason the Asynchronous Ajax Request. – itzmukeshy7 Apr 30 '17 at 5:43
  • The name will not get set until the callback occurs which is after the code in unit has finished. – Eric Apr 30 '17 at 5:51
8

You can take help of callback to get the updated value after the Ajax call:

Helper

userName : function(component, callbackMathod) {
    //loading user related data
    var action = component.get("c.getUserName");
    action.setCallback(this, function(response){
        var state = response.getState();
        if (state === "SUCCESS") {
            component.set("v.Name", response.getReturnValue());
            alert('Called in helper: ' + component.get("v.Name"));
            if(callbackMathod){
                callbackMathod();
            }
         }
    });
    $A.enqueueAction(action);   
},

Controller

doinit : function(component, event, helper) {
    helper.userName(component, function(){
        alert('Called in controller: ' + component.get("v.Name"));
    }); 
}

Component

<aura:handler name="init" value="{!this}" action="{!c.doinit}"/>

<aura:attribute name="Name" type="String" /> 
  • 1
    you are just awesome sir :) – Abhi Tripathi Apr 30 '17 at 6:17
4

As mentioned in the comment ,this is happening because in javascript the order of execution is not sequential like apex .

You generally do not need to access anything in your controller as the view is binded to the attribute and you can do further logic in the callback .

userName : function(component) {
//loading user related data
var action = component.get("c.getUserName");
action.setCallback(this, function(response){
    var state = response.getState();
    if (state === "SUCCESS") {
        component.set("v.Name", response.getReturnValue());
       //do your logic here .You can create functions or further callbacks or promises 

     }
  });
   $A.enqueueAction(action);   
 }

If you really want to understand the async behaviour.In the controller for some fun you can simply put a timeout function like below

doinit : function(component, event, helper) {

 helper.userName(component);
 window.setTimeout(
 $A.getCallback(function() {
    if (component.isValid()) {
        alert(component.get("v.Name"));
    }
 }),1000);
}

Caution : Do not use this timeout method for any business logic .Its just for fun and help you understand how javascript is asynchronous in nature and even though the code block will be sequential the order of execution is not as place your code block .Here is an in depth articles to understand callbacks

Instead provide a callback implementation like below

({
    doinit : function(component, event, helper) {
        helper.userName(component,function(){
            alert(component.get("v.Name"));
        });
       }
   })

({
    userName : function(component,callback) {
    //loading user related data
    var action = component.get("c.getUserName");
    action.setCallback(this, function(response){
        var state = response.getState();
        if (state === "SUCCESS") {
            component.set("v.Name", response.getReturnValue());
           // alert('$$$' + component.get("v.Name"));
           if(callback){
                callback();
            }
         }
    });
    $A.enqueueAction(action);   
}
})
  • There is a chance that @Abhi don't get the value in controller even after 1 second maybe because of the network speed and the processing time taken by Apex. So, even for the testing we should take help of callback method; – itzmukeshy7 Apr 30 '17 at 6:00
  • @itzmukeshy7 Completely agree .I have added a caution statement .Infact i would prefer all logic in the helper only .The reason why i have timeout is to demonstrate the async nature of javascript for an apex developer – Mohith Shrivastava Apr 30 '17 at 6:01
  • the time out thing will be good for some time, but in my case I am having multiple helper functions, so for that call back method will be best, thanks for your help guys – Abhi Tripathi Apr 30 '17 at 6:18
  • 1
    Time out was to demonstrate the asynchronous behavior of JavaScript language and not to be used in the code .You should not chain multiple helper function in controller like that .it will be hard to maintain and debug and you will easily run into callback hell .A callback hell is common problem when you manage too many functions .An approach with ES6 promises will be elegant when you have so many functions . – Mohith Shrivastava Apr 30 '17 at 6:21

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.