skip to Main Content

The conventional way to reference an HTML element is Svelte is to introduce a variable and bind:this the element to the variable. Like this

<script>
  let divName;
</script>

<div bind:this={divName}></div>

In this way we can use the variable divName to reference that element and use it call functions or applying styles.

I’m facing problems when trying to do the same with an element inside a conditional block. In particular when referencing an element which is just became visible. For example

<script>

function enable(){
  someCondition = true;
  if (someCondition) divName.innerText = 'hello';
}

</script>

{#if someCondition}
  <div bind:this={divName}></div>
{/if}

Even if the condition is satisfied, when trying to access the element I get the error divName is null.

A workaround is to wait a few milliseconds between making the element visible and actually referencing it. I made a full working example on repl. In a real application, this doesn’t always works, plus it’s not extremely nice.

I was wondering if anyone know the reason for this and what is the correct way to handle these situations. Thank you very much.

3

Answers


  1. In your example it’s probably better to not bind an element in a conditional block but if you’re asking in general how to easily update the bound element after it’s bound, this would work:

    <script>
    let divName;
    let someCondition;
    
    $: {
      if (divName) {
        divName.innerText = 'hello';
      }
    }
    
    function enable() {
      someCondition = true;
    }
    </script>
    
    <button on:click={enable}>Enable</button>
    
    {#if someCondition}
      <div bind:this={divName}></div>
    {/if}

    I don’t know how to do it in the new Svelte syntax yet but the idea is that the "divName.innerText" becomes a computed value that depends on whether or not divName is truthy. The outer condition of "someCondition" will control the divName element and divName controls divName.innerText.

    Login or Signup to reply.
  2. To get a reference to an element when it’s created you can use an action

    tutorial / tutorial

    <script>
        let visible = false
        
        function handleVisible(node) {
            console.log(node)
        }
    </script>
    
    <button on:click={() => visible = !visible}>
      click
    </button>
    
    {#if visible}
        <div use:handleVisible>...</div>
    {/if}
    
    Login or Signup to reply.
  3. I think the simplest solution is to use Svelte’s reactivity and wait for the divTrue binding to exist:

    <script>
        let check = true;
        let divTrue;
    
        function toggle() {
            check = !check;
        }
    
        $: if (divTrue) {
            divTrue.innerText = 'you can see me';
        }
    </script>
    
    <button on:click={toggle}>Toggle</button>
    {#if check}
        <div bind:this={divTrue}></div>
    {/if}
    

    I am guessing your are simplifying your code for this question, but I am having a hard time understanding why you would set the text via an element’s innerText property rather than just putting it in your markup:

    {#if check}
        <div>you can see me</div>
    {/if}
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search