package binding
Ordering
- Alphabetic
Visibility
- Public
- Protected
Type Members
- macro class html extends Annotation with StaticAnnotation
An annotation to convert XHTML literals to data-bindable DOM nodes.
An annotation to convert XHTML literals to data-bindable DOM nodes.
Author:
杨博 (Yang Bo) <[email protected]>
- Annotations
- @compileTimeOnly("enable macro paradise to expand macro annotations")
XHTML literals with text attributes
@html val myDiv = myDiv.value.nodeName should be("DIV") myDiv.value.className should be("my-class") myDiv.value.tabIndex should be(42)
Nested XHTML literals with interpolation:
@html val myDiv2 = text<span style={"color: blue;"} tabIndex={99}></span> {myDiv.bind} myDiv2.watch() myDiv2.value.outerHTML should be(""" text<span style="color: blue;" tabindex="99"></span> html """)
, Special character in attribute names
@html val myMeta = <meta http-equiv="refresh" content="30"/> myMeta.watch() myMeta.value.outerHTML should be("""<meta http-equiv="refresh" content="30">""")
, Opaque type aliases of HTMLInputElement
@html val myMeta = <input name="myInput" type="radio"/> myMeta.watch() myMeta.value.outerHTML should be("""<input name="myInput" type="radio">""")
, Element list of XHTML literals
@html val myDivs = myDivs.watch() import org.scalajs.dom.html.Div inside(myDivs.value) { case collection.Seq(div1: Div, div2: Div, div3: Div) => div1.nodeName should be("DIV") div1.hasAttribute("class") should be(false) div1.className should be("") div2.title should be("my title") div2.hasAttribute("class") should be(true) div2.className should be("") div3.className should be("my-class") }
, Text interpolation in an element
@html val monadicDiv = {"text"} monadicDiv.watch() assert(monadicDiv.value.outerHTML == " text")
, Changing text
import com.thoughtworks.binding.Binding.Var val v0 = Var("original text") @html val monadicDiv = <span> {v0.bind} </span> monadicDiv.watch() assert(monadicDiv.value.outerHTML == " <span> original text </span> ") v0.value = "changed" assert(monadicDiv.value.outerHTML == " <span> changed </span> ")
, for
/yield
expressions in XHTML interpolationimport com.thoughtworks.binding.Binding.Vars val v0 = Vars("original text 0","original text 1") @html val monadicDiv = <span> { for (s <- v0) yield <b>{s}</b> } </span> monadicDiv.watch() val div = monadicDiv.value assert(monadicDiv.value.outerHTML == " <span> <b>original text 0</b><b>original text 1</b> </span> ") v0.value.prepend("prepended") assert(div eq monadicDiv.value) assert(monadicDiv.value.outerHTML == " <span> <b>prepended</b><b>original text 0</b><b>original text 1</b> </span> ") v0.value.remove(1) assert(div eq monadicDiv.value) assert(monadicDiv.value.outerHTML == " <span> <b>prepended</b><b>original text 1</b> </span> ")
, for
/yield
/if
expressions in XHTML interpolationimport com.thoughtworks.binding.Binding import com.thoughtworks.binding.Binding.Var import com.thoughtworks.binding.Binding.Vars final case class User(firstName: Var[String], lastName: Var[String], age: Var[Int]) val filterPattern = Var("") val users = Vars( User(Var("Steve"), Var("Jobs"), Var(10)), User(Var("Tim"), Var("Cook"), Var(12)), User(Var("Jeff"), Var("Lauren"), Var(13)) ) def shouldShow(user: User): Binding[Boolean] = Binding { val pattern = filterPattern.bind if (pattern == "") { true } else if (user.firstName.bind.toLowerCase.contains(pattern)) { true } else if (user.lastName.bind.toLowerCase.contains(pattern)) { true } else { false } } @html def tbodyBinding = { <tbody>{ for { user <- users if shouldShow(user).bind } yield <tr><td>{user.firstName.bind}</td><td>{user.lastName.bind}</td><td>{user.age.bind.toString}</td></tr> }</tbody> } @html val tableBinding = { <table class="my-table" title="My Tooltip"><thead><tr><td>First Name</td><td>Second Name</td><td>Age</td></tr></thead>{tbodyBinding.bind}</table> } tableBinding.watch() assert(tableBinding.value.outerHTML == """<table class="my-table" title="My Tooltip"><thead><tr><td>First Name</td><td>Second Name</td><td>Age</td></tr></thead><tbody><tr><td>Steve</td><td>Jobs</td><td>10</td></tr><tr><td>Tim</td><td>Cook</td><td>12</td></tr><tr><td>Jeff</td><td>Lauren</td><td>13</td></tr></tbody></table>""") filterPattern.value = "o" assert(tableBinding.value.outerHTML == """<table class="my-table" title="My Tooltip"><thead><tr><td>First Name</td><td>Second Name</td><td>Age</td></tr></thead><tbody><tr><td>Steve</td><td>Jobs</td><td>10</td></tr><tr><td>Tim</td><td>Cook</td><td>12</td></tr></tbody></table>""")
, Dynamc attributes
@html val myBr = <br data:toString="+©" data:applyDynamic="value"/> myBr.watch() myBr.value.outerHTML should be("""<br tostring="+©" applydynamic="value">""")
, Changing attribute values
import com.thoughtworks.binding.Binding.Var val id = Var("oldId") @html val myInput = <input data:applyDynamic={id.bind} data:custom={id.bind} name={id.bind} id={id.bind} onclick={ _: Any => id.value = "newId" }/> myInput.watch() assert(myInput.value.outerHTML == """<input applydynamic="oldId" custom="oldId" name="oldId" id="oldId">""") myInput.value.onclick(null) assert(myInput.value.outerHTML == """<input applydynamic="newId" custom="newId" name="newId" id="newId">""")
, A child node must not be inserted more than once
an[IllegalStateException] should be thrownBy { @html val child = <hr/> @html val parent = <span>{child.bind}</span><span>{child.bind}</span> parent.watch() }
, Seq in DOM
import org.scalajs.dom.document @html def myUl = { {Seq( - data1, - data2)} } val div = document.createElement("div") html.render(div, myUl) div.firstChild.childNodes.length should be(2)
, XHTML comments
import org.scalajs.dom.document @html def comment = val div = document.createElement("div") html.render(div, comment) assert(div.innerHTML == " ")
, Escape
import org.scalajs.dom.document @html def escaped =  $minus val div = document.createElement("div") html.render(div, escaped) assert(div.innerHTML == " $minus")
, Entity references
import org.scalajs.dom.document @html def entity = my text < > © λ val div = document.createElement("div") html.render(div, entity) assert(div.innerHTML == """ © λ my-class">my text < > © λ""")
, Process instructions
@html val myXmlStylesheet = <?my-instruction my data?> myXmlStylesheet.watch() myXmlStylesheet.value.target should be("my-instruction") myXmlStylesheet.value.data should be("my data")
, CDATA sections are not supported in HTML documents
import scala.scalajs.js a[js.JavaScriptException] should be thrownBy { @html val myCData = <![CDATA[my data]]> myCData.watch() }
, XML namespaces
import scala.language.dynamics import org.scalajs.dom.document import org.scalajs.dom.raw._ import com.thoughtworks.binding.Binding import com.thoughtworks.binding.Binding.BindingInstances.monadSyntax._ object svg { object texts extends Dynamic { @inline def selectDynamic(data: String) = new html.NodeBinding.Constant.TextBuilder(data) } object elements { object svg extends Curried { @inline def applyBegin = new html.NodeBinding.Constant.ElementBuilder(document.createElementNS("http://www.w3.org/2000/svg", "svg").asInstanceOf[SVGSVGElement]) } object text extends Curried { @inline def applyBegin = new html.NodeBinding.Constant.ElementBuilder(document.createElementNS("http://www.w3.org/2000/svg", "text").asInstanceOf[SVGTextElement]) } } @inline def interpolation = Binding object values { sealed trait FontStyle case object normal extends FontStyle case object italic extends FontStyle case object oblique extends FontStyle } object attributes { def font$minusstyle(value: values.FontStyle) = { new html.NodeBinding.Constant.AttributeBuilder.Untyped(_.setAttribute("font-style", value.toString)) } def font$minusstyle(binding: Binding[values.FontStyle]) = { new html.NodeBinding.Interpolated.AttributeBuilder( element => binding.map { value => element.setAttribute("font-style", value.toString) } ) } } } implicit final class SvgUriOps(uriFactory: html.autoImports.xml.uris.type) { @inline def http$colon$div$divwww$u002Ew3$u002Eorg$div2000$divsvg = svg } @html val mySvg1 = <svg xmlns="http://www.w3.org/2000/svg"><text font-style="normal">my text</text></svg> mySvg1.watch() mySvg1.value.outerHTML should be("""<svg><text font-style="normal">my text</text></svg>""") import svg.values.normal @html val mySvg2 = <svg:svg xmlns:svg="http://www.w3.org/2000/svg"><svg:text font-style={normal}>my text</svg:text></svg:svg> mySvg2.watch() mySvg2.value.outerHTML should be("""<svg><text font-style="normal">my text</text></svg>""")
Examples: