Methods in Lightning components do not return a value, also came to the same outcome as yourself.
However, I did learn to use and love component events with dynamic event handlers. What you can do from the calling component is fire a component event from within the component you wish to call the method on currently and attach a dynamic event handler for the component finishes processing.
So for example, you can fire an event from where you want to fire the method now like so:
otherComponent.getEvent('provide').fire();
Then also attach a dynamic event handler to listen for a response:
otherComponent.addHandler('responseEvent', component, 'c.handlingControllerAction');
The approach has the benefit of decoupling your components and if you need your other component to do asynchronous work then you can as also the response event would be fired asynchronously. It also allows multiple components to listen out for this event and also react accordingly.
Find more information on the Salesforce help:
https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/js_cb_dynamic_handler.htm
Hope this helps!
I think that after spending few hours I found the answer for the above. Still not sure if it's a bug or a feature of the framework, but definately it has something to do with how secure objects are constructed.
You need to make sure all possible properties for the object are defined (even if null) when you call component.set("v.obj", obj);
for the first time.
Here is example component & controller, with one simple attribute (initialized on init), and two buttons calling log & set functions of controller:
<aura:component >
<aura:attribute name="testAtr" type="Object" access="global"/>
<aura:handler name="init" value="{!this}" action="{!c.initialize}"/>
<p><a onclick="{!c.logAtr}">Console Log Parent</a></p>
<p><a onclick="{!c.setSth}">Set Something</a></p>
</aura:component>
({
initialize : function(component, event, helper) {
var obj = {};
obj.data = 'test';
// obj.someNewProperty = null;
component.set("v.testAtr", obj);
},
logAtr : function(component, event, helper) {
console.log(component.get("v.testAtr.someNewProperty"));
},
setSth : function(component, event, helper) {
var testAtr = component.get("v.testAtr");
testAtr.someNewProperty = 'New Property';
component.set("v.testAtr", testAtr);
},
})
If the line obj.someNewProperty = null;
in initialize
method is commented out, console.log
returns undefined
even if you call setSth
method that actually sets value of obj.someNewProperty
.
If the line obj.someNewProperty = null;
in initialize
method is present, console.log
returns null before calling setSth
method and 'New Property'
after calling it.
EDIT:
But this has some drawbacks. Let's imagine we have a simple form for sObject. You need to initialize object with all the possible properties. If you don't do this - no values will be kept. If these lines: acc.Name = null; acc.Phone = null; acc.Account_Status__c = null;
are commented as in below example - value put in the input text is not bind to testAcc
attribute.
<aura:component >
<aura:attribute name="testAcc" type="Account" access="global"/>
<aura:handler name="init" value="{!this}" action="{!c.initialize}"/>
<p>Name: <ui:inputText value="{!v.testAcc.Name}"/></p>
<p>Phone: <ui:inputText value="{!v.testAcc.Phone}"/></p>
<p>Status: <ui:inputText value="{!v.testAcc.Account_Status__c}"/></p>
<p><a onclick="{!c.logAcc}">Console Log Acc</a></p>
</aura:component>
({
initialize : function(component, event, helper) {
var acc = {};
// acc.Name = null;
// acc.Phone = null;
// acc.Account_Status__c = null;
component.set("v.testAcc", acc);
},
logAcc : function(component) {
console.log(component.get("v.testAcc"));
}
})
Best Answer
The
<aura:method>
declaration belongs on the component receiving the call. The method is considered part of the public API for that component.In your scenario, the method would be declared on the parent, which is inverted from the typical scenario where child-to-parent communication uses events and parent-to-child communication uses public methods. Your child component will need to receive a reference to its parent and store it in an attribute in order to make the method call. (See example below).
The presence of
<aura:attribute>
declarations as part of the<aura:method>
is a little confusing. The method's attributes actually define the parameters of the function that's being declared, and are independent of the attributes of both the calling and receiving component. The parameters passed to an<aura:method>
are always dynamic insofar as they are passed in JavaScript, not declared in markup.The example in the
<aura:method>
documentation is illuminating. I'm adding a bit of outer structure here to clarify. In your scenario, the receiving component is the parent, and the calling component is the child, which has an attributeparent
to hold a reference to its parent component.Receiving Component Markup
Receiving Component Controller
Calling Component Markup
Calling Component Controller
When we invoke the
<aura:method>
, we specify the parameters as part of a JavaScript method call, rather than using Lightning value binds to establish them. It's more or less like any other method call. When we do this, we can source values from our (child) component's attributes, or from any other data source available in the context.Here, we grab the value of a component attribute on the child and pass it as a parameter up to the parent, along with a static value.
See Calling Component Methods.