Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Documentation] Support for Set and Map in {{each}} and {{each-in}} is not documented #20568

Open
jelhan opened this issue Nov 4, 2023 · 4 comments

Comments

@jelhan
Copy link
Contributor

jelhan commented Nov 4, 2023

{{each}} and {{each-in}} helpers support native JavaScript Set and Map since Ember 3.2.0. But it's not documented.

The could lead to wrong assumption that it's not officially supported. See typed-ember/glint#645 for a recent example.

Support was implemented in #16399. It was released as a bug fix. Documentation was not updated since than.

Should be mentioned at least in https://api.emberjs.com/ember/5.4/classes/Ember.Templates.helpers/methods/each?anchor=each and https://api.emberjs.com/ember/5.4/classes/Ember.Templates.helpers/methods/each-in?anchor=each-in. Maybe additionally in the guides at https://guides.emberjs.com/release/components/looping-through-lists/ as well.

@chancancode
Copy link
Member

chancancode commented Nov 15, 2023

Ah yes, seems good to document. With the caveat that – I think it doesn't "update". What I mean is that:

class MyComponent {
  things = new Set();

  @action addThing(thing) {
    this.things.add("thing");
  }

  <template>
    {{#each this.things as |item|}}...{{/each}}
    <button {{on "click" this.addThing "new thing"}}>Add</button>
  </template>
}

I think in this case after the initial render the {{#each}} block will not re-render. This is not to say thing things inside the block won't update, just that the {{#each}} block itself won't notice items being added or removed.

On the other hand, this would trigger the loop to be invalidated:

class MyComponent {
  @tracked things = new Set();

  @action addThing(thing) {
    this.things.add("thing");
    // this line here
   this.things = things;
  }

  <template>
    {{#each this.things as |item|}}...{{/each}}
    <button {{on "click" this.addThing "new thing"}}>Add</button>
  </template>
}
  • But I don't know this is something we want to recommend people do?
  • Can you verify what I said was true?
  • Can you verify whether, without the @tracked, whether things = new TrackedSet(); works with the {{#each}} out of the box? (I think it should, and if it does, then I think that's what we should recommend in the guides)

@jelhan
Copy link
Contributor Author

jelhan commented Nov 15, 2023

Both invalidating the Set as well as using TrackedSet works. Same for Map/TrackedMap.

I don't see a need to document it. It's the same with array and object. It needs to be tracked in order to be reactive.

I haven't tested. I'm using TrackedSet and TrackedMap a lot. It's working as expected. Only Glint struggles with typing of {{for-each}} with TrackedMap.

@NullVoxPopuli
Copy link
Sponsor Contributor

I think documenting it would be immensely helpful for folks.

Many don't expect that Iterables are iterable, (partly due to not thinking about iterables in that way / as something you can iterate over)

@chancancode
Copy link
Member

I think they just meant no need to specifically call out that you need to use a tracked version of the iterable for it to update. I suppose so. Just make sure the example do that then (or do it in accordance of whatever existing documentation guidelines are doing for similar things).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants