raquo on master
Docs: Fix typo in link (compare)
raquo on gh-pages
Deploy website Deploy website … (compare)
raquo on gh-pages
Deploy website Deploy website … (compare)
raquo on v0.12.1
raquo on master
Docs: Add Ajax live example Docs: Inputs and form state exa… Fix: Remove debug logging from … and 2 more (compare)
cls.maybe := None
, what's the "default" ?
abstract class ComplexProp[T](name: String) {
var values: List[T]
def separator: String // " " for cls, ";" for styleAttr
def stringified: List[String] // List[T] => List[String]
def render(parentElem: HtmlElement): Unit = {
parentElem.setAttribute(name) = stringified.mkString(separator)
}
}
DefaultAttrValue
that may or may not completely remove the attribute, all modifier instances (cls, idAttr, styleAttr, name etc.) would be based on either SimpleProp or ComplexProp.
.maybe
that are attached to things where it doesn't make sense, but cannot be used because there is no implicit instance in scope
Thanks ever so much to the people who have helped me get this far... this was my POC... which I'm super happy with.
Number 3 for me was super exciting... as it means that I can wheel in Vega, which is very good at data viz, and access it's events back in laminar, which appears to be very good at everything else!
baby steps... but I think it's cool :-)!
https://example.org/#/person/1234
. Does Waypoint support this kind of route? I can’t figure it out. Alternatively, are there some docs for how to set up SBT to serve my app while developing so that the routes work like they would on a server? (with the hash style I can just open the JS file in a browser). I guess this may be just a general Scala.js question, but if anyone can point me in the right direction I would appreciate it.
root
at the start of your path..import urldsl.errors._
import urldsl.language._
import urldsl.vocabulary._
object WaypointExtras {
val frag = PathSegment.simplePathSegment(
s => if (s.content == "#") Right(()) else Left(DummyError.dummyErrorIsPathMatchingError.wrongValue("#", s.content)),
_ => Segment("#")
)
}
@balhoff The last version of URL-DSL can match URL fragments. You need Waypoint 0.3.0 for this.
Although, I don't actually know how if it will work to match fragment URLs on a file:// URL. You'll need to try. You'll probably need to encode your route as root / "path" / "to" / "your" / "file.html" / endOfSegments / fragment[String]
or something like that
Let's say I got a Var[NonEmptyString]
and I'd like to create a Var[String]
from that (which does nothing if you try to set an empty String), what's the quickest (most readabl) way to go about it instead of creating two more variables?
Basically I'm looking for zoom with the signature def zoom[A, B](in: A => B)(out: B => Option[A])
.
Actual use case is form text input that should not be empty (or any other validation, really). Feel like it'd be a common pattern in the FE
def contramapOpt[B](f: B => Option[A]): Observer[B]
extension on Observer[A]
, but I guess having this on a Var would be nice too..
zoom
under the hood. To convert B => Option[A] into B => A, you want to emit the parent var's current value when no update is desired. I'm not sure if this implementation would be 100% robust in the face of data races, but that's the best you can do if you want a DerivedVar like this (and not a pair of derived Signal and Observer). This could be implemented robustly in Airstream core but we'd need to change DerivedVar slightly.
implicit class ObserverExt[A](val ob: Observer[A]) extends AnyVal {
def contramapOpt[B](f: B => Option[A]): Observer[B] = {
new Observer[B] {
override def onNext(nextValue: B): Unit = {
f(nextValue) match {
case Some(a) => ob.onNext(a)
case None => () // do nothing
}
}
override def onError(err: Throwable): Unit = ob.onError(err)
override def onTry(nextValue: Try[B]): Unit = nextValue match {
case Success(value) =>
f(value) match {
case Some(s) => ob.onTry(Success(s))
case None => () // do nothing
}
case Failure(e) => ob.onTry(Failure(e))
}
}
}
}
This is what I did (just on Observer instead of Var). I don't think it's possible to implement it in terms of zoom (since in the case of None we won't emit any events, but the interface of zoom does not allow you to express this)
Observer
manually, you should add error handling code similar to Observer.fromTry (see docs for observer error handling) for it to be well behaved
since in the case of None we won't emit any events, but the interface of zoom does not allow you to express this
Right that's why when you want to emit None, you should read the parent Var's value and emit that instead, when implementing in terms of zoom
. Signals perform a ==
check before emitting so the Var will not actually emit anything in this case because its value didn't change.
toIntOption
so it's actually less efficient that way since the conversion function is run twice (once for the isDefinedAt and then once again to get the value)
ob
a lot of it is handled already, but not if f
throws. You could implement onTry method as ob.onTry(nextValue.map(f))
and call into it from onNext and onError to solve that
Observer.withRecover
for exception safety (I think this should work)
split
on Var[List[A]]
as well into something like Var[List[Var[A]]
? Use case is a form with array of subforms