udash

How to apply a jquery-ui widget when an input is dynamically loaded


I want to use the JQueryUI spinner widget on inputs that are loaded using the udash repeat method. I have tried the following approach:

val integers = SeqProperty(Seq[Int](5, 7))

val rootNode =
    div(
        button(onclick:= add, "Add"),
        repeat(integers) { p =>
            val in = input(value := p.get, cls := "my-spinner").render
            $(in).spinner()
            in
        }
    )

def add = { () =>
    integers.append(Random.nextInt(10))
}

def main(args: Array[String]): Unit = {
    dom.document.getElementById("root").appendChild(rootNode.render)
    // $(".my-spinner").spinner()
}

But this does not produce the complete jquery-ui dom that is required. When I inspect my dom tree all I get is this:

<div>
   <button>Add</button>
   <input value="5" class="my-spinner ui-spinner-input" aria-valuenow="5" autocomplete="off" role="spinbutton" />
   <input value="7" class="my-spinner ui-spinner-input" aria-valuenow="7" autocomplete="off" role="spinbutton" />
</div>

Whereas if I comment out the last line, to apply the spinner after the dom is loaded, I get the complete xml:

<div>
   <button>Add</button>
   <span class="ui-spinner ui-corner-all ui-widget ui-widget-content" style="height: 21px;">
      <input value="5" class="my-spinner ui-spinner-input" aria-valuenow="5" autocomplete="off" role="spinbutton" />
      <a tabindex="-1" aria-hidden="true" class="ui-button ui-widget ui-spinner-button ui-spinner-up ui-corner-tr ui-button-icon-only" role="button">
         <span class="ui-button-icon ui-icon ui-icon-triangle-1-n" />
         <span class="ui-button-icon-space" />
      </a>
      <a tabindex="-1" aria-hidden="true" class="ui-button ui-widget ui-spinner-button ui-spinner-down ui-corner-br ui-button-icon-only" role="button">
         <span class="ui-button-icon ui-icon ui-icon-triangle-1-s" />
         <span class="ui-button-icon-space" />
      </a>
   </span>
   <span class="ui-spinner ui-corner-all ui-widget ui-widget-content" style="height: 21px;">
      <input value="7" class="my-spinner ui-spinner-input" aria-valuenow="7" autocomplete="off" role="spinbutton" />
      <a tabindex="-1" aria-hidden="true" class="ui-button ui-widget ui-spinner-button ui-spinner-up ui-corner-tr ui-button-icon-only" role="button">
         <span class="ui-button-icon ui-icon ui-icon-triangle-1-n" />
         <span class="ui-button-icon-space" />
      </a>
      <a tabindex="-1" aria-hidden="true" class="ui-button ui-widget ui-spinner-button ui-spinner-down ui-corner-br ui-button-icon-only" role="button">
         <span class="ui-button-icon ui-icon ui-icon-triangle-1-s" />
         <span class="ui-button-icon-space" />
      </a>
   </span>
</div>

But of course this approach is not sufficient as I need to be able to load my inputs dynamically. Is there a way I can apply the spinner widget dynamically?


Solution

  • I was able to resolve the issue by wrapping my input in a div element and appending a script element after the input. From within this script, I used a callback mechanism to allow code to be run every time a new input gets loaded. The callback mechanism wasn't totally straight forward as I can only call javascript code when defining a script tag. So I added a non-native JS type to take care of this. I generalised the whole approach using a component. I have outlined this solution on ScalaFiddle