WebSharper 4.2.8 released with in-document template binding

Loic Denuziere

Loic Denuziere

Mar 26, 2018

Reading time:

3 mins

Share via:

We are happy to announce the release of WebSharper 4.2.8 and WebSharper.UI 4.2.3.

Install project templates for this release:

In-document template binding

The main highlight of this release is a WebSharper.UI feature called in-document template binding.

Declaring a template with the type provider parameter clientLoad = ClientLoad.FromDocument loads templates directly from the DOM. This makes it convenient to work on the HTML file without having to recompile your F# code. However, before this release, this feature was limited: it only applied to sub-templates, ie. templates declared within the document using ws-template or ws-children-template attributes. Such an instantiation removes the corresponding element from the DOM and creates a client-side Doc that can be inserted using a function such as Doc.RunById.

With in-document template binding, it is now possible to bind holes declared directly in the document. This is done by using the .Bind() method instead of .Doc(), .Elt() or .Create(). This new method returns unit and directly binds the declared holes to the DOM, without the need to detach and re-attach a sub-template.

Here is an example, which sets the content of the <div> when the user clicks the button:

<html>
  <head><!-- head contents... --></head>
  <body>
    <input ws-var="Username" />
    <button ws-onclick="Click">Click me!</button>
    <div>${ConfirmedUsername}</div>
  </body>
</html>
type MyTemplate = Template<"index.html", clientLoad = ClientLoad.FromDocument>

[<SPAEntryPoint>]
let Main() =
    let confirmed = Var.Create ""
    MyTemplate()
        .ConfirmedUsername(confirmed.View)
        .Click(fun e -> confirmed := !e.Vars.Username)
        .Bind()

For a more comprehensive example, you can also check Adam's new getting started tutorial implementing a Bulma-styled login form with Bind().

The above example uses Bind() in an SPA project, which is the most typical use case. But it is also possible to use it in a client-server application, where the server side uses the same template, potentially binding some holes itself. For this, you need to add the parameter keepUnfilled = true to your server-side .Doc() instantiation. Otherwise, all unbound holes would be removed by the server-side rendering engine, and there would be nothing left to bind on the client.

Full changes

Features

  • ui#161 Add .Bind() : unit template terminating method to directly bind holes to the current document. This is available on the client-side only if the template is declared with ClientLoad.FromDocument.

  • ui#161 Add optional argument .Doc(keepUnfilled: bool) for the server side to leave unfilled holes in the document, so that they can be used on the client side by .Bind().

  • ui#160 Add extension methods to bring C# in line with F#:

    // Extensions on ListModel<K, T>:
    View<IEnumerable<V>> Map(Func<T, V> f);
    View<IEnumerable<V>> Map(Func<K, View<T>, V> f);
    View<IEnumerable<V>> MapLens(Func<K, Var<T>, V> f);
    Doc Doc(Func<T, Doc> f);
    Doc Doc(Func<K, View<T>, Doc> f);
    Doc DocLens(Func<K, Var<T>, Doc> f);
    ListModel<K, V> Wrap(Func<V, T> extract, Func<T, V> wrap, Func<V, T, V> update);
    
    // Extension on Var<FSharpList<T>>:
    Doc DocLens(Func<T, K> key, Func<K, Var<T>, Doc> f);
    

Fixes

  • #931 Add downwards assembly redirects. This fixes an assembly load failure when a non-WebSharper-compiled referenced assembly uses FSharp.Core > 4.4.1.0.

Happy coding!

Read more from

Can’t find what you were looking for? Drop us a line.

Loic Denuziere
Found a typo?

This blog post is hosted on GitHub here. Feel free to file a ticket or send a PR.

Newsletter

We will not spam you or give your details to anyone.