Bob you've probably addressed this already but facing a similar problem, I have had success using the component.getReference() method rather than component.get() to set attribute values on dynamically created components. So instead of:
swapInThree : function(component, event, helper) {
var acc=component.get("v.acc");
var str=component.get("v.str");
you could try:
swapInThree : function(component, event, helper) {
var acc=component.getReference("v.acc");
var str=component.getReference("v.str");
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 effective mechanism by which two components can work is by using Events .Lightning framework works on Event driven paradigm .
You will have a Publisher component that will publish event and you will have a listener that will listen to the events and handle the events .
An excellent blogs from this is below
https://developer.salesforce.com/blogs/developer-relations/2015/03/lightning-component-framework-custom-events.html
http://bobbuzzard.blogspot.com/2015/05/lightning-component-events.html
Observe how easy it is to create events for a component
Like OOPS you can also use concept of interface and implement the interface
Set the implements system attribute in the aura:component tag to the name of the interface that you are implementing.
A component can implement an interface and extend another component. aura:component extends="ns1:cmp1" implements="ns2:intf1"
An interface can extend multiple interfaces using a comma-separated list. aura:interface extends="ns:intf1,ns:int2"