aurelia / framework

The Aurelia 1 framework entry point, bringing together all the required sub-modules of Aurelia.
MIT License
11.76k stars 623 forks source link

UI is not re-rendered when Set is used. #971

Closed sahithyandev closed 4 years ago

sahithyandev commented 4 years ago

I'm submitting a feature request

Please tell us about your environment:

Current behavior: I am using Set to store the classNames of an object. I am binding the class with Set.join(' ') (I wrote the join method for Set, it works like Array.prototype.join). When I add value to the Set object, the UI doesn't change.

I think that there are no prototype overrides for Set.

Expected/desired behavior:

https://gist.run/?id=41630e04f1399a58fd693b8f7611c028

bigopon commented 4 years ago

For you main Q related to

<div class.bind="Array.from(classNames).join(' ')">

It is how Aurelia works, nothing wrong with your extension. The expression Array.from(classNames).join(' ') will have only classNames property observed. Which means as long as the value of classNames hasn't changed, the binding to update class on the <div/> won't be updated. Note that mutation of an object/array/set/map doesn't count as property change. As following example:

app.classNames = new Set();
app.classNames.add('my-class'); // set mutation, not property change
app.classNames = new Set(); // property change

So for your scenario, the easiest way is to:

<div class.bind="Array.from(classNames).join(' ') | identity :classNames.size"

The part identity :classNames.size will tell Aurelia to also observe mutation on classNames Set, so that when you add new class to it, the binding will update.

Identity value converter can be simple like this;

import { valueConverter } from 'aurelia-framework';

@valueConverter('identity')
export class IdentityValueConverter {
  toView(val) {
    return val;
  }
}

And register it globally:

aurelia
  .use
  .globalResources(IdentityValueConverter)
sahithyandev commented 4 years ago

Thank you for your response. I will test it out and get back to you soon.

sahithyandev commented 4 years ago

I found another workaround to do this. Instead of using identities, I created a new Set and updated the classNames with it. So now, it is not a mutation and it works.

See it running here. (Click on the Hello World text to see it) https://gist.run/?id=41630e04f1399a58fd693b8f7611c028

bigopon commented 4 years ago

@KSahithyan yup, it works well that way too. So it's up to you, based on different situation/scenarios. Glad you got it work the way you want.

For reproduction of issues/bugs, I'd recommend this https://gist.dumber.app, it can be considered the successor of gist.run

bigopon commented 4 years ago

@KSahithyan @EisenbergEffect I guess we can close this?