Svelte: Refs inside each blocks

Created on 13 Mar 2017  路  9Comments  路  Source: sveltejs/svelte

Currently they're not allowed, but maybe this...

{{#each things as thing}}
  <div ref:things/>
{{/each}}

...could result in component.refs.things being an array. The array need not correspond to the each block expression, since you might have things like this:

{{#each things as thing, i}}
  {{#if i % 2}}
    <div ref:things/>
  {{/if}}
{{/each}}

{{#each rows as y}}
  {{#each columns as x}}
    <div ref:cells/>
  {{/each}}
{{/each}}

Or is it confusing having two subtly different meanings for ref?

enhancement pending clarification

Most helpful comment

Closing as this will be fixed in v3 (with bind:this={things[i]} etc)

All 9 comments

You could call it arrayref, maybe...

I suppose if it's documented well enough, anything would work OK here :)

IMHO sticking with ref is going to be the most predictable. There is a good chance I would try that before even looking at the docs.

I agree. I thought it would be like that until I checked the docs and saw it isn't available yet. Makes sense to me.

In this example:

{{#each rows as y}}
  {{#each columns as x}}
    <div ref:cells/>
  {{/each}}
{{/each}}

Supposing that component.ref.cells were an array, what would the index be? Without some sort of indexing, if you ever wanted to do anything with ref:cells you'd always end up looping over the array doing a find.

A contrived example:

{{#each rows as y, yIndex}}
  {{#each columns as x, xIndex}}
    <Cell ref:cells isOddRow="{{yIndex % 2 > 0}}" />
  {{/each}}
{{/each}}
<button on:click="color()">color odd rows</button>
<script>
export default {
  methods: {
    color() {
      (this.ref.cells || []).forEach(cell => {
        if (cell.get('isOddRow')) {
          cell.set({ hoverColor: 'green' })
        }
      })
    }
  }
}
</script>

I just ran into a use case where I wanted an array of refs to elements inside an each loop. 馃憤

@Rich-Harris pointed me to this issue when I raised this in the chat room (although note my need was simply to loop within a method, rather than an #each block):

"Wish this.refs was an array of refs rather than an object - or we had a this.children array of any child components. I've a page with 6 graphs and other stuff and wanted to simply loop through and refresh any graphs, doesn't look like it is possible and for now I have to hard-code it"

I'd suspect this will be a more common need the more users start using svelte.

const children = Object.keys(this.refs).map(k => this.refs[k]);

How about something like:

```
{#each things as thing}

{/each}

Closing as this will be fixed in v3 (with bind:this={things[i]} etc)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

davidcallanan picture davidcallanan  路  3Comments

st-schneider picture st-schneider  路  3Comments

Rich-Harris picture Rich-Harris  路  3Comments

robnagler picture robnagler  路  3Comments

ricardobeat picture ricardobeat  路  3Comments