15

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);
    },
})
3
  • 6
    This looks like bug, but since it's not documented, I'm not sure anyone outside of one of the internal Lightning developers could say more.
    – sfdcfox
    Mar 20, 2018 at 15:38
  • I didn't even know the # statement. What is it supposed to do? Mar 20, 2018 at 17:47
  • 1
    # is a by-value expression. Instead of maintaining a reference, it'll be the raw result of whatever was passed in.
    – Kris Gray
    Mar 20, 2018 at 18:26

1 Answer 1

7

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.

8
  • I haven't seen cmp.clearReference() before is that part of the open api? Mar 20, 2018 at 20:30
  • 1
    Thanks for your detailed response! Clearing the reference only fixed it for line 6, but 4 and 5 are still immutable. My suggestion to your internal decision would be, that if someone overrides the old value, it's definitely his fault or even his/her intention, I would override it by design. It's a public value, so we need to treat it properly and be aware of this behaviour (as lightning does it with add/removeClass).
    – itsmebasti
    Mar 20, 2018 at 21:07
  • Yes, clearReference() is platform api exposed auraframework.org/auradocs#reference?topic=api:Component
    – Kris Gray
    Mar 20, 2018 at 21:13
  • 1
    What do you mean? The code to test it is above and I tested it as described.
    – itsmebasti
    Mar 21, 2018 at 7:15
  • 1
    Well I'll be a monkeys uncle. We don't clear for computed references, only for references. ({!v.foo} is a reference, {!1+1} is a computed reference). Following up with the architect of the project to see whats the proper solution.
    – Kris Gray
    Mar 23, 2018 at 0:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .