[SalesForce] Lightning change handler – value based on parent object

I'm trying to understand the value change handler as described in the documentation Detecting Data Changes with Change Handlers.

I am confused by the event handler when a component attribute is bound to a parent object.

For example i would expect the following component change handler event to always have the value/oldValue as a string.

<aura:component description="testCmp">
    <aura:attribute name="value" type="string"/>
    <aura:handler name="change" value="{!v.value}" action="{!c.handleChange}"/>

    <aura:attribute name="valueHistory" type="String"/>

    Current Value: {!v.value}
    History:
    <pre>
        {!v.valueHistory}
    </pre>
</aura:component>

with the following controller:-

({
    handleChange: function(component, event, helper) {

        var params = event.getParams();
        var oldValue = params.oldValue;
        var value = params.value;

        var valueHistory = component.get('v.valueHistory') || '';
        valueHistory += 'New Value: ' + JSON.stringify(value) + '\n';

        component.set('v.valueHistory', valueHistory);

    }
})

This component by itself works as expected with string history printing as:-

New Value: "Hello 0"
New Value: "Hello 1"
New Value: "Hello 2"
New Value: "Hello 3"
New Value: "Hello 4"

However if i bind the value attribute to a parent object, then the change handler seems to take on the parent object when if fires. ie

Parent Component:-

<aura:application access="GLOBAL" >

    <aura:attribute name="valueObj" type="object" />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

    <button onclick="{!c.incrementMessage}">Change Message (parent)</button>

    <c:testCmp value="{!v.valueObj.message}"/>


</aura:application>

Parent controller:-

({
    doInit: function(component, event, helper) {
        var valueObj = {
            message: 'Hello ' + 0,
            count: 0
        };

        component.set('v.valueObj', valueObj);
    },

    incrementMessage: function(component, event, helper) {

        var valueObj = component.get('v.valueObj');
        valueObj.count++;
        valueObj.message = 'Hello ' + valueObj.count;


        component.set('v.valueObj', valueObj);
    }
})

In this case the original change handler now has an object value:-

New Value: {"message":"Hello 0","count":0}
New Value: {"message":"Hello 1","count":1}
New Value: {"message":"Hello 2","count":2}

There seems to be no way to detect this difference in behaviour and i've had to resort to using component.get('v.value') in the change handler instead of the event value.

Am i missing something here or is this a bug?

Best Answer

Are you trying to avoid the changes if happening from parent component? Means don't want to fire the change event if value is changed in parent component If so then can you try this expression:

<c:testCmp value="{#v.valueObj.message}"/>

Basically using "#" in attribute binding avoid the creation of standard framework change event handlers. So if the value is getting updated at parent level it will not affect the child attribute.

Related Topic