The handler name in your child component should match the registered name in the parent component. i.e., the handler in child component should be like this:
<aura:handler name="clrValues" event="c:ClearValues" action="{!c.clear}"/>
--UPDATE--
I think a better approach for parent-to-child communication is to use <aura:method>
as listed in lightning docs and here
To do this, you should define a method in child component like this:
<aura:method name="sampleMethod" action="{!c.clear}" access="PUBLIC">
You should then have an id when you refer it inside your parent component like this:
<c:ChildComponent textValue="test" aura:id="cComp"/>
Then in the clear method of the parent component, you should invoke the child method like this:
var childCmp = component.find("cComp")
childCmp.sampleMethod();
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
If the parent is simply concerned about getting notifications on its data changing, you can use an aura:valueChange event in the parent directly:
If you want to do it as an event from the child, then you've got to go down the path of using aura:registerEvent in the child component, which ultimately means you have to fire the change event manually, in which case you can then use the onchange mechanism from your original post.
In your child component:
And in your controller code: