Instances of
WebAsk
for compound types can be derived from instances of its components
derivation of views
One of the major strengths of using Uniform for web development is that the generic web interpreter can automatically define how a form should be visually represented and encoded and persisted for you.
If you define a WebAsk[Html, A]
and a WebAsk[Html, B]
along with a
few simple rules to define composition you can have for free
WebAsk[Html,(A,B)]
, WebAsk[Html,Either[A,B]]
, or
WebAsk[Html,C]
where C
is any combination of A
and B
.
import ltbs.uniform._, common.web._
// we'll use this as a simple representation
// of HTML, in practice you'd use something more
// substantial like scalatags `Tag` or twirl `Html`
case class Html(value: String)
// Implement InferWebAsk
object MyWidgets extends InferWebAsk[Html] {
// define how to render a product
// (f.e. using a fieldset)
def renderAnd(
pageKey: List[String],
fieldKey: List[String],
tell: Option[Html],
breadcrumbs: Breadcrumbs,
data: Input,
errors: ErrorTree,
messages: UniformMessages[Html],
members: Seq[(String, Html)]
): Html = ???
// define how to render a coproduct
// (f.e. using radio buttons)
def renderOr(
pageKey: List[String],
fieldKey: List[String],
tell: Option[Html],
breadcrumbs: Breadcrumbs,
data: Input,
errors: ErrorTree,
messages: UniformMessages[Html],
alternatives: Seq[(String, Option[Html])],
selected: Option[String]
): Html = ???
// define a few simple primative types
implicit def askInt : WebAsk[Html, Int] = ???
implicit def askString : WebAsk[Html, String] = ???
implicit def askBool : WebAsk[Html, Boolean] = ???
}
Once you have an implementation of InferWebAsk
you can use it to
provide derived types -
import MyWidgets._
implicit def askTuple: WebAsk[Html, (Int, Boolean)] = implicitly
sealed trait One
case class Two(a: String, b: Boolean)
case class Three(a: String, c: Either[Boolean, Int])
implicit def askHierarchy: WebAsk[Html, One] = implicitly
What this means in effect is that in return for a little bit of up-front work in defining the way fields should be composed together you gain the ability to manipulate the data structures at will and have the interface adapt itself.
This is valuable at all points through the product lifecycle but particularly so during prototyping.