These are chat archives for ThoughtWorksInc/Binding.scala

7th
Oct 2016
杨博 (Yang Bo)
@Atry
Oct 07 2016 00:32
@raquo Yes. You can add a -Xprint:all flag to Scala compiler and see the equivalent plain expressions generated by Binding.scala
Since this question is asked frequently. @raquo Would you mind if you could add it on FAQ page?
Nikita Gazarov
@raquo
Oct 07 2016 00:36
Can do, once I figure out how to do this :)
Nikita Gazarov
@raquo
Oct 07 2016 01:31
Hrm, unfortunately I don’t think I personally can make use of this output, it’s just too dense :/
e.g.
val element$macro$1: org.scalajs.dom.html.Div = com.thoughtworks.binding.dom.Runtime.TagsAndTags2.div.apply().render;
            partialAppliedMonadic$macro$226.typeClass.map[com.thoughtworks.binding.Binding[com.thoughtworks.binding.Binding.BindingSeq[org.scalajs.dom.raw.Node]], com.thoughtworks.binding.Binding[org.scalajs.dom.html.Div]]({
              implicit def currentTargetReference$macro$5: com.thoughtworks.binding.dom.Runtime.CurrentTargetReference[org.scalajs.dom.html.Div] = new com.thoughtworks.binding.dom.Runtime.CurrentTargetReference[org.scalajs.dom.html.Div](element$macro$1);
              partialAppliedMonadic$macro$226.typeClass.map[com.thoughtworks.binding.Binding[com.thoughtworks.binding.Binding[com.thoughtworks.binding.Binding.Constants[org.scalajs.dom.raw.Text]]], com.thoughtworks.binding.Binding[com.thoughtworks.binding.Binding.BindingSeq[org.scalajs.dom.raw.Node]]]({
                val partialAppliedMonadic$macro$33: com.thoughtworks.binding.Binding.type = com.thoughtworks.binding.Binding;
An earlier compiler stage (namer) produces slightly more readable output, but it does not include the macros transformations.
      $buf.$amp$plus({
        {
          new _root_.scala.xml.Elem(null, "div", _root_.scala.xml.Null, $scope, false, ({
            val $buf = new _root_.scala.xml.NodeBuffer();
            $buf.$amp$plus(new _root_.scala.xml.Text("\n      "));
            $buf.$amp$plus({
              {
                var $md: _root_.scala.xml.MetaData = _root_.scala.xml.Null;
                $md = new _root_.scala.xml.UnprefixedAttribute("onclick", ((event: Event) => contacts.get.$plus$eq(Contact(Var("Yang Bo"), Var("yang.bo@rea-group.com")))), $md);
                new _root_.scala.xml.Elem(null, "button", $md, $scope, false, ({
                  val $buf = new _root_.scala.xml.NodeBuffer();
                  $buf.$amp$plus(new _root_.scala.xml.Text("\n        Add a contact\n      "));
                  $buf
                }: _*))
              }
            });
            $buf.$amp$plus(new _root_.scala.xml.Text("\n    "));
            $buf
          }: _*))
        }
      });
杨博 (Yang Bo)
@Atry
Oct 07 2016 01:37
Em... There are two internal phases of macro transfromations. Unfortunately scalac does not separate them.
I guess you need some intermedia expressions between the two internal phases
Nikita Gazarov
@raquo
Oct 07 2016 01:45
Oh well. It’d be great if it was possible to build the DOM nodes with an API smilar to scalatags, but implementing this looks beyond my current scala skill level, unfortunately. Still a great project.
杨博 (Yang Bo)
@Atry
Oct 07 2016 01:46

In the first internal phase:

@dom def renderInput(source: Var[String]) = {
  <input value={source.bind}/>
}

will be translated to

def renderInput(source: Var[String]) = Binding {
  val myInput = TagsAndTags2.input().render
  val autoBindValue = Binding {
    myInput.value = source.bind
  }
  autoBindValue.bind
  myInput
}
Then, in the second internal phase, the Binding block will be translated to map and flatMap
Nikita Gazarov
@raquo
Oct 07 2016 02:06
Hah, I thought ok, maybe let’s try to compile Scala XML with function calls to scala.xml.Elem. Not sure if the macros would pick that up, but that's impossible anyway because scala.xml._ is not compiled for Scala.js
杨博 (Yang Bo)
@Atry
Oct 07 2016 02:11
You are right. It's impossible for Scala.js.
Michele Sciabarra
@sciabarra
Oct 07 2016 18:57
How can I concatenate 2 BindingSeq[Node] ?
William Ho
@williamho
Oct 07 2016 19:21
@dom val concatenated = seq1.bind ++ seq2.bind (or val concatenated = Binding { seq1.bind ++ seq2.bind }) is one way of doing it
Michele Sciabarra
@sciabarra
Oct 07 2016 19:22
could super.render().bind ++ <div>...</div> work?
William Ho
@williamho
Oct 07 2016 19:25
what does super.render() return in this case? a BindingSeq[Node]?
Michele Sciabarra
@sciabarra
Oct 07 2016 19:25
yes
I am basically applying cake pattern to a UI
William Ho
@williamho
Oct 07 2016 19:26
I think it would work if you use :+ instead of ++ in this case (appending a single Node element to a seq)
Michele Sciabarra
@sciabarra
Oct 07 2016 19:27
yup got it
so BindingSeq is just a Seq
William Ho
@williamho
Oct 07 2016 19:27
when you call .bind on it, yeah
Michele Sciabarra
@sciabarra
Oct 07 2016 19:28
got it I missed the "bind" step
Michele Sciabarra
@sciabarra
Oct 07 2016 19:42
how I do something better than this:
@dom override def render(): Binding[BindingSeq[Node]] =
<div id="world">
{super.render().bind}
</div>
<div></div>
How I can avoid the empty <div>
William Ho
@williamho
Oct 07 2016 19:47
You can wrap the first div with Constants, which is also a BindingSeq:
Constants(<div id="world">blah</div>)
Michele Sciabarra
@sciabarra
Oct 07 2016 19:48
great
THX!