Is your feature request related to a problem? Please describe.
It has a lot of possible applications. Here's the latest problem I faced today.
I have a big paginated list, that has page buttons in the bottom of the list, and I want to scroll the list to the first item whenever I change the page. I want to use scrollIntoView method, so I need a ref to the first item of the list.
Describe the solution you'd like
It seems to be quite safe to allow undefined as a possible value for ref 鈥斅爄t would just mean to not bind this element/component to any variable.
{#each arr as item, index}
<p bind:this={index === 0 ? ref : undefined}>{item}</p>
{/each}
It also seems legit from developer point of view to allow dynamic ref target with code like this:
{#each arr as item, index}
<p bind:this={cond(item) ? ref : ref2}>{item}</p>
{/each}
Describe alternatives you've considered
Right now I do this in multiple ways.
Array of refs. REPL. In two words:
<script>
let refs = [];
</script>
{#each arr as item, index}
<p bind:this={refs[index]}>{item}</p>
{/each}
and then use refs[0] or refs[refs.length - 1] to get certain elements.
I think:
Custom class name. Assign a conditional class via class:custom-name={index === 0}, and then use document.querySelector to get the element with this class. It is bad because of two reasons: class name clashes (need to come up with unique name) and class name duplication (one in <script> and one in layout).
How important is this feature to you?
Not that much, it just seems like a good feature to have. I'm not aware of the internals of Svelte, but I assume adding any kind of dynamic code in element binding would be a lot of pain, because it most probably happens during compile time and not in the runtime.
Additional context
Same ideas were mentioned in this comment.
If the expression inside the bind:this={...} isn't assumed to be directly usable as the left hand side of an assignment, I'm not sure that there's a clear way to handle this. How do we know what level to 'stop' at when evaluating this and to assume is to be treated as the LHS of an assignment? What would bind:this={[a[x], a[y], a[z]][k]} do? Bind to index k in this array literal? Bind to either a[x], a[y], or a[z] depending on the value of k?
As I said, the second option, that lets you swap target variables, can be vague. I have yet to find a feasible use case for this feature, tbh.
The first option is quite feasible to me though. undefined logic seams pretty straightforward.
What would
bind:this={[a[x], a[y], a[z]][k]}do? (1) Bind to indexkin this array literal? (2) Bind to eithera[x],a[y], ora[z]depending on the value ofk?
This example is a bit artificial, but I would say the second option should work.
It's just like how it works in all the vdom frameworks. I'm not aware of the internals of Svelte, so it might be pain to implement, but I would say it should be quite obvious for a developer.
I am trying to do the following, any ideas for other solutions?
<script>
const items = [...];
let selectedIndex = 3;
let selectedElement;
$: selectedElement, (() => {
selectedElement.getClientBoundingRect().doSomeStuff();
})();
</script>
{#each items as item, i}
<div class="item" class:selected={selectedIndex == i} bind:this={selectedIndex == i ? selectedElement : undefined}/>
{/each}
@davidcallanan Simplest solution for now would be to store all the refs and only use the one you need.
<script>
const items = [...];
let selectedIndex = 3;
let refs = [];
$: refs[selectedIndex]?.getClientBoundingRect().doSomeStuff();
</script>
{#each items as item, i}
<div class="item" class:selected={selectedIndex == i} bind:this={ref[i]}/>
{/each}
Most helpful comment
@davidcallanan Simplest solution for now would be to store all the refs and only use the one you need.