thoughtworksinc / binding.scala Goto Github PK
View Code? Open in Web Editor NEWReactive data-binding for Scala
License: MIT License
Reactive data-binding for Scala
License: MIT License
https://scalafiddle.io/sf/uwj5QcD/2
import com.thoughtworks.binding.dom
import com.thoughtworks.binding.Binding.Vars
import org.scalajs.dom._
@dom
def render = {
val logs = Vars("Hello", "Binding.scala")
<div id="foo">
<div>
{ for { log <- logs } yield <div>{ log }</div> }
</div>
<a href="#" onclick={(evt:Event) => logs.get += "foo";showProp()}>ClikeMe</a>
</div>
}
def showProp() = {
val e = document.getElementById("foo")
if(e.hasAttribute("foo")) {
window.alert(e.getAttribute("foo"))
} else {
e.setAttribute("foo", "bar")
}
}
dom.render(document.body, render)
As above example indicates, the outer div[id=foo]
seems recreated every time clicking the link.
This is absoultely not what precise-data-binding
means
如题
One of the biggest pain points with any new framework is, I need a widget that does X, someone already implemented X, can I use their widget?
For example, with React using jQuery plugins is tricky (see for example http://tech.oyster.com/using-react-and-jquery-together/)
Of course there are already the cross-language issues, e.g. with scala.js you have to write a facade, and until http://scala-lang.org/blog/2016/10/19/scalajs-bundler.html came along there were the issues with using npm modules.
If I could somehow use Binding.scala for the page but throw React components and jQuery plugins inside in places, and/or use Binding.scala inside a React component, it would be a much easier sell (to myself).
I'm guessing that would require lifecycle hooks (similar to using jQuery with React).
It would be nice to have instructions how to achieve this (or at least a FAQ saying it's not possible, if that's the case).
Thanks!
I was investigating if Binding.scala
's FXML support will work for one of my personal projects, and quickly ran into issue trying to create a simple table:
import javafx.application.Application
import javafx.stage._
import javafx.scene._
import javafx.scene.control._
import com.thoughtworks.binding.Binding.Constants
import com.thoughtworks.binding._
final class FxmlTest extends Application {
@fxml override def start(primaryStage: Stage): Unit = {
type StringTable = TableView[String]
val scene: Binding[Scene] =
<Scene>
<StringTable> {Constants("Hello", "Flatmap")}</StringTable>
</Scene>
fxml.show(primaryStage, scene)
}
}
object FxmlTest {
def main(args: Array[String]): Unit = {
Application.launch(classOf[FxmlTest], args: _*)
}
}
Results in this error:
[error] [E1] src/mco/ui/FxmlTest.scala
[error] type mismatch;
[error] found : com.thoughtworks.binding.Binding.Constants[String]
[error] required: javafx.collections.ObservableList[String]
[error] L16: <StringTable> {Constants("Hello", "Flatmap")}</StringTable>
[error] L16: ^
It does not work if I use Seq
instead, too.
I found a related issue on SO but could not find a way to trigger implicit conversion, if there is one.
import com.thoughtworks.binding._
import org.scalajs.dom._
@dom def main = {
<select>
<option value="">Volvo</option>
<option value="saab">Saab</option>
<option value="opel">Opel</option>
<option value="audi">Audi</option>
</select>
}
dom.render(document.body, main)
ScalaFiddle.scala:8: error: type mismatch;
found : scala.collection.immutable.Nil.type
required: String
Volvo
^
see https://scalafiddle.io/sf/SYResoO/1
P.S. in scalafiddle I use Binding.scala 9.0.3, since newer versions do not work in scalafiddle
object Something {
@dom
def apply(user: Var[Option[User]], logoutCall: () => Unit): Binding[Div] = {
<div>
{
user.bind match {
case None =>
<div/>
case Some(_) =>
<a class = "btn btn-secondary" style = "float:right;" onclick = { (e: Event) ⇒ logoutCall() }>
Logout
</a>
}
}
</div>
}
in terminal
>
scalafmt
[trace] Stack trace suppressed: run last web-client/compile:scalafmt for the full output.
error java.lang.IncompatibleClassChangeError: Found class fastparse.core.Parser, but interface was expected
>
last web-client/compile:scalafmt
java.lang.IncompatibleClassChangeError: Found class fastparse.core.Parser, but interface was expected
at scala.meta.internal.tokenizers.LegacyScanner.getXml(LegacyScanner.scala:959)
at scala.meta.internal.tokenizers.LegacyScanner.fetchLT$1(LegacyScanner.scala:336)
at scala.meta.internal.tokenizers.LegacyScanner.fetchToken(LegacyScanner.scala:344)
at scala.meta.internal.tokenizers.LegacyScanner.nextToken(LegacyScanner.scala:233)
at scala.meta.internal.tokenizers.LegacyScanner.foreach(LegacyScanner.scala:1022)
at scala.meta.internal.tokenizers.ScalametaTokenizer.uncachedTokenize(ScalametaTokenizer.scala:154)
at scala.meta.internal.tokenizers.ScalametaTokenizer.tokenize(ScalametaTokenizer.scala:34)
at scala.meta.internal.tokenizers.ScalametaTokenizer$$anon$2.apply(ScalametaTokenizer.scala:263)
at scala.meta.tokenizers.Api$XtensionTokenizeDialectInput.tokenize(Api.scala:23)
at scala.meta.tokenizers.Api$XtensionTokenizeInputLike.tokenize(Api.scala:12)
at scala.meta.internal.parsers.ScalametaParser.scannerTokens$lzycompute(ScalametaParser.scala:207)
at scala.meta.internal.parsers.ScalametaParser.scannerTokens(ScalametaParser.scala:207)
at scala.meta.internal.parsers.ScalametaParser.(ScalametaParser.scala:168)
at scala.meta.internal.parsers.ScalametaParser$$anon$201.apply(ScalametaParser.scala:3650)
at scala.meta.parsers.Api$XtensionParseDialectInput.parse(Api.scala:21)
at scala.meta.parsers.Api$XtensionParseInputLike.parse(Api.scala:10)
at org.scalafmt.Scalafmt$.format(Scalafmt.scala:51)
at org.scalafmt.cli.Scalafmt210.format(Scalafmt210.scala:46)
at org.scalafmt.cli.Scalafmt210.format(Scalafmt210.scala:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.scalafmt.sbt.HasScalaFmt.org$scalafmt$sbt$HasScalaFmt$$handleFile(HasScalaFmt.scala:85)
at org.scalafmt.sbt.HasScalaFmt$$anonfun$writeFormattedContentsToFiles$1$$anonfun$apply$3.apply(HasScalaFmt.scala:54)
at org.scalafmt.sbt.HasScalaFmt$$anonfun$writeFormattedContentsToFiles$1$$anonfun$apply$3.apply(HasScalaFmt.scala:54)
at scala.collection.Iterator$class.foreach(Iterator.scala:727)
at scala.collection.parallel.immutable.ParHashSet$ParHashSetIterator.foreach(ParHashSet.scala:76)
at scala.collection.parallel.ParIterableLike$Foreach.leaf(ParIterableLike.scala:975)
at scala.collection.parallel.Task$$anonfun$tryLeaf$1.apply$mcV$sp(Tasks.scala:54)
at scala.collection.parallel.Task$$anonfun$tryLeaf$1.apply(Tasks.scala:53)
at scala.collection.parallel.Task$$anonfun$tryLeaf$1.apply(Tasks.scala:53)
at scala.collection.parallel.Task$class.tryLeaf(Tasks.scala:56)
at scala.collection.parallel.ParIterableLike$Foreach.tryLeaf(ParIterableLike.scala:972)
at scala.collection.parallel.AdaptiveWorkStealingTasks$WrappedTask$class.compute(Tasks.scala:165)
at scala.collection.parallel.AdaptiveWorkStealingForkJoinTasks$WrappedTask.compute(Tasks.scala:514)
at scala.concurrent.forkjoin.RecursiveAction.exec(RecursiveAction.java:160)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
error java.lang.IncompatibleClassChangeError: Found class fastparse.core.Parser, but interface was expected
Current implementation use Vector
, which consumes linear time when an element is inserted or removed in the middle of a BindingSeq
.
While, finger tree could be O(1)
or O(log n)
.
To reproduce:
sbt run clean compile
clean
) hangs with this stack trace:[error] /tmp/fxml/FxmlSample.scala:10: exception during macro expansion:
[error] java.lang.InterruptedException
[error] at java.lang.Object.wait(Native Method)
[error] at java.lang.Object.wait(Object.java:502)
[error] at com.thoughtworks.binding.fxml$Macros$.<init>(fxml.scala:555)
[error] at com.thoughtworks.binding.fxml$Macros$.<clinit>(fxml.scala)
[error] at com.thoughtworks.binding.fxml$Macros$XmlTransformer$$anonfun$com$thoughtworks$binding$fxml$Macros$XmlTransformer$$transformXmlValue$1.applyOrElse(fxml.scala:1228)
[error] at com.thoughtworks.binding.fxml$Macros$XmlTransformer$$anonfun$com$thoughtworks$binding$fxml$Macros$XmlTransformer$$transformXmlValue$1.applyOrElse(fxml.scala:1219)
[error] at scala.PartialFunction$Lifted.apply(PartialFunction.scala:223)
[error] at scala.PartialFunction$Lifted.apply(PartialFunction.scala:219)
[error] at com.thoughtworks.Extractor$PartialFunctionToExtractor$$anon$3.unapply(Extractor.scala:98)
[error] at com.thoughtworks.binding.fxml$Macros$XmlTransformer$$anonfun$com$thoughtworks$binding$fxml$Macros$XmlTransformer$$expand$1.applyOrElse(fxml.scala:1415)
[error] at com.thoughtworks.binding.fxml$Macros$XmlTransformer$$anonfun$com$thoughtworks$binding$fxml$Macros$XmlTransformer$$expand$1.applyOrElse(fxml.scala:1414)
[error] at scala.PartialFunction$Lifted.apply(PartialFunction.scala:223)
[error] at scala.PartialFunction$Lifted.apply(PartialFunction.scala:219)
[error] at com.thoughtworks.Extractor$PartialFunctionToExtractor$$anon$3.unapply(Extractor.scala:98)
[error] at com.thoughtworks.binding.fxml$Macros$XmlTransformer$$anonfun$com$thoughtworks$binding$fxml$Macros$XmlTransformer$$transformBlock$1$$anonfun$37.apply(fxml.scala:1427)
[error] at com.thoughtworks.binding.fxml$Macros$XmlTransformer$$anonfun$com$thoughtworks$binding$fxml$Macros$XmlTransformer$$transformBlock$1$$anonfun$37.apply(fxml.scala:1425)
[error] at scala.collection.immutable.List.flatMap(List.scala:327)
[error] at com.thoughtworks.binding.fxml$Macros$XmlTransformer$$anonfun$com$thoughtworks$binding$fxml$Macros$XmlTransformer$$transformBlock$1.applyOrElse(fxml.scala:1425)
[error] at com.thoughtworks.binding.fxml$Macros$XmlTransformer$$anonfun$com$thoughtworks$binding$fxml$Macros$XmlTransformer$$transformBlock$1.applyOrElse(fxml.scala:1423)
[error] at scala.PartialFunction$Lifted.apply(PartialFunction.scala:223)
[error] at scala.PartialFunction$Lifted.apply(PartialFunction.scala:219)
[error] at com.thoughtworks.Extractor$PartialFunctionToExtractor$$anon$3.unapply(Extractor.scala:98)
[error] at com.thoughtworks.binding.fxml$Macros$XmlTransformer.transform(fxml.scala:1445)
[error] at com.thoughtworks.binding.fxml$Macros$$anonfun$macroTransform$1.apply(fxml.scala:1484)
[error] at com.thoughtworks.binding.fxml$Macros$$anonfun$macroTransform$1.apply(fxml.scala:1465)
[error] at com.thoughtworks.sde.core.Preprocessor.replaceDefBody(Preprocessor.scala:35)
[error] at com.thoughtworks.binding.fxml$Macros.macroTransform(fxml.scala:1464)
CDATA sections can be created if coalescing
flag is off.
Note that coalescing
flag is on by default and scala -Xxml:-coalescing
will turn off the flag.
Hello, is it possible to extend the list of supported tags and attributes ?
value svg is not a member of object com.thoughtworks.binding.dom.Runtime.TagsAndTags2
[error] @dom def render = <svg></svg>
I made a step-by-step tutorial on Bindings.scala and Google Maps:
https://github.com/pme123/Binding.scala-Google-Maps
Maybe it helps someone.
Curious if I'm doing something wrong in this example code: https://scalafiddle.io/sf/HzKl1uG/4
If the checkbox is off, and I change the number, then when I click checkbox on, it doesn't reflect the number I've typed. But if dates are displayed, then changing the number has the proper effect.
Reported by @kahliburke on Gitter:
https://gitter.im/ThoughtWorksInc/Binding.scala?at=597958a6329651f46ec7752c
I read through the issues of custom tags but must admit, that i did not fully understand if it is possible to extend Binding.scala with custom tags.
Say OnsenUI defines a custom tag <ons-page>
, how can i use this in Binding.scala?
I tried the following wrapper
package onsen
import com.thoughtworks.binding._
import Binding._
import org.scalajs.dom.document
import org.scalajs.dom.raw.Node
import scala.language.implicitConversions
import scala.scalajs.js
import scala.scalajs.js.annotation.JSName
case class OnsenBasicComponentBuilder(tagName: String) {
def render = this
var modifier: Binding[String] = _
@dom def build = {
val element=document.createElement(tagName)
element.setAttribute("modifier",modifier.bind)
element
}
}
object Onsen {
implicit def autoBinding[A](a: A): Binding[A] = ???
implicit final class CustomTags(x: dom.Runtime.TagsAndTags2.type) {
def OnsPage() = OnsenBasicComponentBuilder("ons-page")
def OnsToolbar() = OnsenBasicComponentBuilder("ons-toolbar")
def OnsToolbarButton() = OnsenBasicComponentBuilder("ons-toolbar-button")
def OnsIcon() = OnsenBasicComponentBuilder("ons-icon")
def OnsButton() = OnsenBasicComponentBuilder("ons-button")
}
implicit def toHtml(x: OnsenBasicComponentBuilder): BindingSeq[Node] = {
Constants(x.build).mapBinding(identity)
}
}
and use it as follows
import onsen.Onsen._
@dom
def page = {
<div>
<OnsPage><OnsToolbar></OnsToolbar></OnsPage>
</div>
}
getting
overloaded method constructor NodeSeqMountPoint with alternatives:
[error] (parent: org.scalajs.dom.raw.Node,childBinding: com.thoughtworks.binding.Binding[org.scalajs.dom.raw.Node])com.thoughtworks.binding.dom.Runtime.NodeSeqMountPoint <and>
[error] (parent: org.scalajs.dom.raw.Node,childBinding: com.thoughtworks.binding.Binding[com.thoughtworks.binding.Binding.BindingSeq[org.scalajs.dom.raw.Node]],dummy: Unit)com.thoughtworks.binding.dom.Runtime.NodeSeqMountPoint <and>
[error] (parent: org.scalajs.dom.raw.Node,childrenBinding: com.thoughtworks.binding.Binding.BindingSeq[org.scalajs.dom.raw.Node])com.thoughtworks.binding.dom.Runtime.NodeSeqMountPoint
[error] cannot be applied to (onsen.OnsenBasicComponentBuilder, com.thoughtworks.binding.Binding.BindingSeq[org.scalajs.dom.raw.Node])
[error] <OnsPage><OnsToolbar></OnsToolbar></OnsPage>
[error] ^
I wrote a simple demo inspired from https://thoughtworksinc.github.io/Binding.scala/#5 ,
but there is a problem that the two input boxes will lost focus after I typed any key.
I'm trying to use FutureBinding with this build config:
libraryDependencies += "com.thoughtworks.binding" %%% "futurebinding" % "latest.release"
libraryDependencies += "com.thoughtworks.binding" %%% "dom" % "latest.release"
enablePlugins(ScalaJSPlugin)
addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full)
At this point latest.release resolved to the version 9.0.1.
And compiler report the following when compiling:
[error] ....../component/ConnectDialog.scala:4: object FutureBinding is not a member of package com.thoughtworks.binding
[error] import com.thoughtworks.binding.FutureBinding
[error] ^
[error] ....../component/ConnectDialog.scala:36: not found: value FutureBinding
[error] {val result = FutureBinding(Ajax.get(s"mock/2"))
[error] ^
[error] two errors found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 2 s, completed 2016-9-20 15:36:30
I have checked the Binding.scala-website project finding out it was compiling with version 8.0.0.
Then I was tried to switch version to 8.0.0 & 9.0.0, both of these versions works well.
Is there something changed at version 9.0.1?
Just a suggestion in case someone wants to have a crack at it (maybe I will, but I doubt ...):
This might be a good starting point, though note the comment at the bottom that explains the problem with raw dom manipulation.
Per Yang's suggestion on gitter:
@dom
itself could be implemented in scala.meta, as@dom
is barely a syntax sugar, forwarding .bind magic to macros in Each/SDE.There are two steps to compile a
@dom
method
@dom
translate your XHTML literal and bind magic to some SDE instructrions- The SDE macro perform monadic translation.
SDE (Specific Domain Extension) is the name of core library shared by both Binding.scala and Each.
... investigate if it is possible to implement a scala.meta version of
@dom
. The current implemention is merely 431 lines of code. https://github.com/ThoughtWorksInc/Binding.scala/blob/10.0.x/dom/src/main/scala/com/thoughtworks/binding/dom.scala
Hi, I would be very glad to have this at the moment. Are there any plans to support ScalaJS 1.0.0-M... ?
See test case here: https://scalafiddle.io/sf/yXNtdXr/0
A workaround is to put the expression with Constants into its own @dom annotated method, or use import scalaz.std.list._ method (as described in https://stackoverflow.com/questions/42498968/when-i-use-binding-scala-i-got-the-error-each-instructions-must-be-inside-a-sd/42498969#42498969)
I want to edit an element after it created dynamically(for example,draw a picture in a canvas).So I tried something like this.
import com.thoughtworks.binding.Binding.{ Var, Vars }
import com.thoughtworks.binding.dom
import org.scalajs.dom.raw.Event
import org.scalajs.dom.document
import org.scalajs.dom.html.TextArea
@dom
def render = {
val div =
<textarea id="myArea" value="value1"></textarea>
val ele = document.getElementById("myArea")
ele.asInstanceOf[TextArea].value = "value2"
div
}
dom.render(document.body, render)
but ele
is null so I can't edit it.Is there any workaround or any promise about when the element will be created so I can trigger the script.
https://scalafiddle.io/sf/cTYNGtw/1 get result 3,4
, which is expected result.
https://scalafiddle.io/sf/cTYNGtw/2 get 3,4,5,6,7,3,4
, which should be wrong.
The only difference is if .bind
is used in the for loop.
I am trying to create a function layout which will return multiple nodes.
@dom
def renderLayout(): Binding[BindingSeq[Node]] = {
val bSNavBar = new BSNavBar(MockData.menuData)
<div class="container">
{bSNavBar.renderNavBar.bind}
</div>
<div class="container">
{bSNavBar.renderNavBar.bind}
</div>
}
If fails to compile with type mismatch : found NodeBuffer
Also the code mentioned in documentation does not compile. type mismatch : found NodeBuffer.
@dom def node: Binding[BindingSeq[org.scalajs.dom.raw.HTMLBRElement]] = <br/><br/>
How to return multiple nodes ?
The current example project is outdated.
We should update link to newer activator templates:
I tried this :
class CustomTag(){
@BeanProperty var field : String = ""
override def toString = s"Person: $field"
}
@JSExport
object Foo {
@fxml def test() = { <CustomTag field="test"/> }
}
[error] java.lang.ClassNotFoundException: sth.pkg.CustomTag
[error] at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
[error] at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
[error] at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
[error] at java.lang.Class.forName0(Native Method)
[error] at java.lang.Class.forName(Class.java:264)
[error] at com.thoughtworks.binding.fxml$Macros.resolvePropertiesForJavaBean(fxml.scala:928)
[error] @FXML def test() = { }
I tried
class CustomTag(@BeanProperty var field:String){
override def toString = s"Person: $field"
}
sth.pkg.CustomTag is not a Java Bean nor a type built from JavaFXBuilderFactory
[error] @FXML def test() = { }
[error] ^
I also tried to create a regular java class :
public class CustomTag {
private String field;
public CustomTag(){
}
public CustomTag(String field){
this.field=field;
}
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
}
and get java.lang.ClassNotFoundException:
I also tried to add an import next to it :
@fxml def test() = {
import sth.pkg.CustomTag
binding.scala
tag on Stackoverflow.com (https://stackoverflow.com/tags/binding.scala/info)binding.scala
tag on Stackoverflow.com including these questions[error] SparkSqlPage.scala:64: value colspan is not a member of org.scalajs.dom.html.TableHeaderCell
[error] <th colspan="6">
[error] ^
[error] one error found
[error] (client/compile:compileIncremental) Compilation failed
[error] Total time: 9 s, completed 2017-1-14 18:46:49
It seems that scalajs-dom support colspan:
scalafiddle ok.
https://scalafiddle.io/sf/Sc0RmDj/3
but. desktop spit out errors.
code
@dom def inlineStyle = {
<section>
<style>
<![CDATA[
.highlight {background-color:gold}
]]>
</style>
<p> Binding.scala. easy to use.
</p>
</section>
}
sbt environment.
scala 2.12
scalajs 0.6.15
libraryDependencies += "com.thoughtworks.binding" %%% "binding" % "latest.release"
libraryDependencies += "com.thoughtworks.binding" %%% "dom" % "latest.release"
libraryDependencies += "com.thoughtworks.binding" %%% "futurebinding" % "latest.release"
libraryDependencies += "com.thoughtworks.binding" %%% "jspromisebinding" % "latest.release"
error message
[error] /Users/baram204/IdeaProjects/learningPixi/src/main/scala/binding/L07_XHTMLliterals.scala:39: overloaded method value domBindingSeq with alternatives:
[error] (text: String)com.thoughtworks.binding.Binding.Constants[org.scalajs.dom.raw.Text] <and>
[error] (node: org.scalajs.dom.raw.Node)com.thoughtworks.binding.Binding.Constants[org.scalajs.dom.raw.Node] <and>
[error] (seq: Seq[org.scalajs.dom.raw.Node])com.thoughtworks.binding.Binding.Constants[org.scalajs.dom.raw.Node] <and>
[error] (bindingSeq: com.thoughtworks.binding.Binding.BindingSeq[org.scalajs.dom.raw.Node])com.thoughtworks.binding.Binding.BindingSeq[org.scalajs.dom.raw.Node]
[error] cannot be applied to (scala.xml.PCData)
[error] <![CDATA[
[error] ^
I'm trying to insert items at specific positions in a Vars
list. I notice that calling insert
on the buffer created by Vars#get
has some unexpected side effects. Specifically, after calling insert
and then calling a method that removes elements (such as .clear()
or .trimEnd(...)
), it doesn't remove elements that I expect.
I've created a ScalaFiddle to demonstrate the issue:
https://scalafiddle.io/sf/SBPcr3y/0
Click "Add random item" a few times and then click "Clear". Not all items get removed from the UI, though it says there are 0 items in the list. Is this a bug or am I using it incorrectly?
import com.thoughtworks.binding
import com.thoughtworks.binding.Binding._
import org.scalajs.dom.raw._
import org.scalajs.dom.document
import scala.scalajs.js.annotation.JSExport
import scala.scalajs.js.JSApp
import scala.util.Random
val initialItems = (1 to 10).map(i => s"initial item $i")
val items = Vars(initialItems: _*)
/**
* Add a few items and click "Clear". Not all items get cleared,
* and the length is incorrect.
*/
binding.dom.render(document.body, listElem(items))
def insertRandom(items: Vars[String]) = {
val buffer = items.get
val index = if (buffer.isEmpty) 0 else Random.nextInt(buffer.length)
buffer.insert(index, s"new item ${Random.nextInt.abs}")
}
@binding.dom
def listElem(listItems: BindingSeq[String]) = {
<div>total items: { listItems.bind.length.toString }</div>
<button onclick={ (e: Event) => insertRandom(items) }>Add random item</button>
<button onclick={ (e: Event) => items.get.clear() }>Clear</button>
<ol>{
listItems.map { item =>
<li>{ item }</li>
}
}</ol>
}
Reasoning:
Look at following example,
val str = Var[String]("foo")
@dom def foo() = {
val strBind = str.bind
<div>
<span>{strBind}</span>
</div>
}
The val strBind = str.bind
makes the whole block rerendered while str
changed.
Auto inline it could make dom change minimal
For example, https://ant.design/components/popconfirm/
// confirm, cancel are functions
<Popconfirm title="Are you sure delete this task?" onConfirm={confirm} onCancel={cancel} okText="Yes" cancelText="No">
<a href="#">Delete</a>
</Popconfirm>
What I expect:
class Popconfirm(title: String, okText: String, cancelText: String, onConfirm: Event => Unit, onCancel: Event => Unit) extend SomeTrait {
@some_anno override def render(body: Element): Element = ???
}
here render
is the function used in macros.
But this test case(https://github.com/ThoughtWorksInc/Binding.scala/blob/11.0.x/fxml/.js/src/test/scala/com/thoughtworks/binding/DateSpec.scala) shows that <Date></Date>
is Binding[Date]
or another type relating to Date
. It seems @fxml
is not suitable for customizing tags to create something like Ant Design.
In #4 (comment) ,
there are tricks to make custom tags work, but it is without any inner html (eg. <a href="#">Delete</a>
).
The following code produces an "each
instructions must be inside a SDE block" error message even though it doesn't doesn't match any of the conditions for when it should normally appear e.g. not within @dom section.
case class CheckboxElement(name: Var[String],
label: Var[String],
checked: Var[Boolean] = Var(false)) extends Component {
@dom def render() = {
<label class="checkbox-inline checkbox-right">
<input name={ name.bind } type="checkbox" class="styled"/>
{ label.bind }
</label>
}
}
In build tools another dependency can easily pull in the newer version and the resulting macro errors are hard to diagnose for new users. It would make sense to update from 0.5.5 to 0.6.0 in order to make the library more approachable.
Now ScalaFiddle: https://scalafiddle.io/ supports Bindings.scala, so the examples on the home page should now enable live editing of source code by embedding ScalaFiddle.
[error] /Developer/test-sdk/shared/src/main/scala/com/naden/namaste/components/elements/CheckboxElement.scala:13:4: overloaded method constructor UnprefixedAttribute with alternatives:
[error] (key: String,value: Option[Seq[scala.xml.Node]],next: scala.xml.MetaData)scala.xml.UnprefixedAttribute <and>
[error] (key: String,value: String,next: scala.xml.MetaData)scala.xml.UnprefixedAttribute <and>
[error] (key: String,value: Seq[scala.xml.Node],next1: scala.xml.MetaData)scala.xml.UnprefixedAttribute
[error] cannot be applied to (String, Boolean, scala.xml.MetaData)
[error] <input name={ name.bind } type="checkbox" class="styled" checked={ checked.bind } />
[error] ^
Appears for the following code:
case class CheckboxElement(name: Var[String],
label: Var[String],
checked: Var[Boolean] = Var(false)) extends Component {
@dom def render() = {
<label class="checkbox-inline checkbox-right">
<input name={ name.bind } type="checkbox" class="styled" checked={ checked.bind } />
{ label.bind }
</label>
}
}
If I remove the checked attribute the error message goes away.
Currently the Binding trait can not be extended easily because some private method and type.
We need this because we want to make our existing code(which has it's own data-binding mechanism) work with Binding.scala together. We want to implement Binding trait for our own data type but find no way to do this.
Do you have a plan to change this ? Or am I missing something?
It seems like accessing nested elements after constructing them using XML literals doesn't work:
val div = <div><div>Nested</div></div>
div.childNodes.length == 0
Rendering div
afterwards works like expected though.
Example: https://scalafiddle.io/sf/6ZzWXB2/2
This should print
nested div: [object HTMLDivElement]
div children: 1
E.g. @fxml <ComboBox/>
I am using IntelliJ as my IDE and it underlines in red all my @dom functions. I tried to open the sample project at https://github.com/ThoughtWorksInc/todo/ and I have the same problem. Is there a way to get rid of this? I have looked at the docs and could not find it.
As it seems related to the use of the macro, is there an "easy" way to define a binding without the macro?
SO Link
Given a component
@dom
def chart = {
<canvas id="chartCanvas"><canvas>
}
How can I init the canvas with some chart library like chartjs when it is loaded to dom ?
This bug occures in 10.0.0-M3
@dom def invalidId = {
<div id="invalid-id"></div>
}
play.sbt.PlayExceptions$UnexpectedException: Unexpected exception[IllegalArgumentException: requirement failed: invalid-id is not a valid identifier]
at play.sbt.run.PlayReload$$anonfun$taskFailureHandler$1.apply(PlayReload.scala:51) ~[na:na]
at play.sbt.run.PlayReload$$anonfun$taskFailureHandler$1.apply(PlayReload.scala:44) ~[na:na]
at scala.Option.map(Option.scala:145) ~[scala-library.jar:na]
at play.sbt.run.PlayReload$.taskFailureHandler(PlayReload.scala:44) ~[na:na]
at play.sbt.run.PlayReload$.compileFailure(PlayReload.scala:40) ~[na:na]
at play.sbt.run.PlayReload$$anonfun$compile$1.apply(PlayReload.scala:17) ~[na:na]
at play.sbt.run.PlayReload$$anonfun$compile$1.apply(PlayReload.scala:17) ~[na:na]
at scala.util.Either$LeftProjection.map(Either.scala:377) ~[scala-library.jar:na]
at play.sbt.run.PlayReload$.compile(PlayReload.scala:17) ~[na:na]
at play.sbt.run.PlayRun$$anonfun$playRunTask$1$$anonfun$apply$2$$anonfun$apply$3$$anonfun$2.apply(PlayRun.scala:61) ~[na:na]
Caused by: java.lang.IllegalArgumentException: requirement failed: invalid-id is not a valid identifier
at scala.Predef$.require(Predef.scala:233) ~[scala-library.jar:na]
at org.scalajs.core.ir.Trees$.requireValidIdent(Trees.scala:61) ~[na:na]
at org.scalajs.core.ir.Trees$Ident.<init>(Trees.scala:45) ~[na:na]
at org.scalajs.core.compiler.JSEncoding$class.encodeLocalSym(JSEncoding.scala:188) ~[na:na]
at org.scalajs.core.compiler.GenJSCode.encodeLocalSym(GenJSCode.scala:31) ~[na:na]
at org.scalajs.core.compiler.GenJSCode$JSCodePhase.genStatOrExpr(GenJSCode.scala:1589) ~[na:na]
at org.scalajs.core.compiler.GenJSCode$JSCodePhase.genStat(GenJSCode.scala:1529) ~[na:na]
at org.scalajs.core.compiler.GenJSCode$JSCodePhase$$anonfun$70.apply(GenJSCode.scala:2714) ~[na:na]
at org.scalajs.core.compiler.GenJSCode$JSCodePhase$$anonfun$70.apply(GenJSCode.scala:2714) ~[na:na]
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) ~[scala-library.jar:na]
I want to make mobile app quick and easy.
so, nativescript is looks good.
There are similar project sri. but I don't want to use facade and learn complex ReactNative and convent new convert way.
so how can I use nativescript with Binding.scala?
I'm a newbee. So I just asking you some advice.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.