Skip to content
Alex Reisberg edited this page Feb 9, 2017 · 46 revisions

I get the error each instructions must be inside a SDE block, how can I fix this?

The code that causes this error is that your bind expression must not be outside of the scope of the @dom macro. This can happen when creating a closure (for example someCollection.map { item <div>{item.bind}</div> }) and can be resolved by:

  • Refactoring the code into its own @dom annotated method.

  • Wrapping the code in a Binding { } block, for example:

    someCollection.map(item => Binding { renderItem(item.bind) } )
  • Converting someCollection to a BindingSeq, for example:

    Constants(someCollection: _*).map { item => <div>{item.bind}</div> }
  • Provide a scalaz.Traverse type class for the collection (Run this example on ScalaFiddle)

    @dom def renderList(data: List[Binding[String]]) = <ol>{
      import scalaz.std.list._ // Type classes for List
      for (b <- data) yield {
        <li>{b.bind}</li>
      }
    }</ol>

How do I create a Binding of HTML node with empty HTML content?

Wrap an HTML comment:

@dom def maybeEmpty: Binding[Node] = {
  if (math.random > 0.5) {
    <div>non-empty content</div>
  } else {
    <!-- empty content -->
  }
}

My input html forms misses focus/empties when a Var changes

Maybe you defined the <input ...> and .bind in the same @dom method and the <input ...> is after .bind. Try to refactor the .bind and <input ...> into separate @dom methods or let the .bind expression nested in another DOM.

For example:

@dom def render(data: Binding[Int]) = {
  val className: String = s"class-name-for-div-${data.bind}"

  // <div> and <input> will be recreated once data changes.
  <div class={className}>
    <input type="text"/>
  </div>
}
@dom def render(data: Binding[Int]) = {
  val myInput = <input type="text"/>
 
  val className: String = s"class-name-for-div-${data.bind}"

  // <div> will be recreated once data changes.
  // <input> will not be recreated.
  <div class={className}>
    {myInput}
  </div>
}
@dom def render(data: Binding[Int]) = {
  // <div> and <input> will not be recreated when data changes.
  // Only the class attribute will be changed.
  <div class={s"class-name-for-div-${data.bind}"}>
    <input type="text"/>
  </div>
}
@dom def render(data: Binding[Int]) = {
  @dom val className: Binding[String] = s"class-name-for-div-${data.bind}"

  // <div> and <input> will not be recreated when dataValue changes,
  // only the class attribute will be changed.
  <div class={className.bind}>
    <input type="text"/>
  </div>
}

I am getting Stack Overflow when compiling.

For complex web views, stack size is not enough. You need to increase it for the compiler. For sbt you can do it adding a .sbtopts in the root of your project with the line:

-J-Xss5m

Intellij complains that I should have Binding[Node] instead of Elem

Intellij doesn't support macro annotation. To make it happy, bring the following implicit into the scope

implicit def makeIntellijHappy(x: scala.xml.Node): Binding[org.scalajs.dom.raw.Node] = ???

This code is never actually executed.

Clone this wiki locally