Passing calculated values to components makes them immutable

I’m calculating a value while I pass it to a component. But for some reason this makes it immutable, so I can’t update it in my component. These are some cases I played with:

<aura:application extends="force:slds">
    <aura:attribute name="value" type="Integer" default="{!1+1}" />

    <c:test value="2" />           //changeable
    <c:test value="{!2}" />        //changeable
    <c:test value="{#2}" />        //changeable
    <c:test value="{!1+1}" />      //immutable
    <c:test value="{#1+1}" />      //immutable
    <c:test value="{!v.value}" />  //immutable (same here, should be bound, but not final)
    <c:test value="{#v.value}" />  //changeable
</aura:application>

So I don’t understand why 4-6 are immutable, there is nothing documented about this!
I guess the last try is my way to go, but this is not how I expected it to work, maybe someone can bring some light into this.

Feel free to play around yourself:

c:test

<aura:component >
    <aura:attribute name="value" type="Integer" />

    <lightning:button label="Change Value to 10" onclick="{! c.changeValue }" />
    {!v.value}
</aura:component>

controller:

({
    changeValue: function(cmp, evt, helper) {
        cmp.set("v.value", 10);
    },
})

Answer

This was intentionally designed this way, and reason for that is an edge case.

You can still change the value, you simply need to clear the reference before setting it first.

({
    changeValue: function(cmp, evt, helper) {
        cmp.clearReference("v.value");
        cmp.set("v.value", 10);
    },
})

Lets tell a little bit of a story here to explain whats going on.

kris:base

<aura:component extensible="true">
 <aura:attribute name="className" type="String" default="padding-bottom"/>
</aura:component>

kris:concrete

<aura:component extends="kris:base">
   <aura:set attribute="className" value="{!'padding-top ' + v.className}">
</aura:component>

As you can see, I’m setting an extended attribute via aura:set. It references back to the attribute you’re already setting.

The expectation is clear to the developer, he wanted to take what the base class specified, and add a bit of additional information.

If he comes along later and does

({
   changeClassName: function(cmp) {
       cmp.set("v.className", "margin-top");
   }
})

Possible values of v.className now

  • “margin-top padding-bottom”
  • “margin-top”

In some situations you may want one value, and in some you’ll want the other. What we decided at the time is that we won’t make a choice. You’ll need to clear the reference yourself, and decide what should happen.

We were recently revisiting this so its possible it’ll change again, this merely explains the reasoning and current state of functionality.

Suggestions welcome.

Attribution
Source : Link , Question Author : Basti , Answer Author : Kris Gray

Leave a Comment