1
comment
on 1/8/2018 11:11 PM

WebSharper 4.1.1 is now available on NuGet, and as a vsix installer on the WebSharper website.

It contains enhancements and fixes to some client-server functionality introduced in WebSharper 4.1 (on.* server-side event handlers pre-compiling any form of quotation), special treatment of IsClient value for conditional compilation for server/client, and other bug fixes.

Documentation: WebSharper 4.1 for C# and WebSharper 4.1 for F#.

The release notes are also found on GitHub.

New features

  • Server-side event handlers (on.*) and ClientSide can take any fixed F# quotation now and translates it to JavaScript.
1
2
3
4
5
div [] [ text "div created on the server" ]
client 
    <@ JavaScript.Console.Log "running client-side code"
       div [] [ text "div created on the client" ]
    @>
  • The IsClient value (WebSharper.Pervasives.IsClient from C#) and their negations (not IsClient and !Pervasives.IsClient) can be used as a condition in branching logic in shared client-server code to make the JavaScript compiler skip the false branch entirely.
1
2
3
    // using WebSharper;
    if (Pervasives.IsClient) { ClientSideMethod(); } else { ServerSideMethod(); }
    var res = Pervasives.IsClient ? ClientSideMethod() : ServerSideMethod();
1
    if IsClient then ClientSideMethod() else ServerSideMethod()

New features in WebSharper.UI

  • Added Lens function to lens into a Var using the .V syntax. Example usage:
1
2
3
Lens(myvar.V.MyField)
// is equivalent to:
myVar.LensAuto(fun x -> x.MyField)
1
This returns creates a `Var<T>` where `T` is the type of `MyField` record field, which gets and sets its value by updating the underlying `myVar`.
  • Add Var<list<T>>.MapLens and .DocLens, similar in functionality to their ListModel counterpart, although with linear-time complexity. Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type Person = { Id: int; Name: string; Age: int }

let people =
    Var.Create (fun p -> p.Id) [
        { Id = 0; Name = "Ann"; Age = 34 }
        { Id = 1; Name = "Brian"; Age = 28 }
        { Id = 2; Name = "Clara"; Age = 43 }
    ]

let editPeople =
    people.DocLens(fun k vp ->
        form [] [
            Doc.Input [] (Lens vp.V.Name)
            Doc.IntInputUnchecked [] (Lens vp.V.Age)
        ]
    )

This ties the inputs to the values in people.Value (of type list<Person>), recreating the immutable list if any of the inputs are changed.

Fixes and improvements

  • An empty F# Map passed to an RPC function is deserialized correctly.
  • The behavior of the Stub attribute on constructors and static methods are now consistent with the documented translation logic since WebSharper 3.0.
  • Multiple server-side event handlers and ClientSide having captured arguments within the same method do not interfere with each other.
  • The client helper in WebSharper.UI is now available again within client-side code. So a div [] [ client <@ div [] [] @> ] in server side-code will create the internal div on the client (the server returning a placeholder) while fully running on the it just creates the internal div basically as if client <@ @> wrapper was not there.
  • Server-side event handlers and ClientSide do not create extra functions in translated JavaScript code if their expression is containing a single static method call. These functions in back-compatibility package WebSharper.UI.Next work the same as in WebSharper 4.0.
  • Some quotation forms were missing when exploring for captured arguments inside server-side on.* event handlers, including tuple gets (used by F# implicitly when passing captured a tuple value to a client-side function taking a tuple, resulting in a runtime failure). This is now working correctly:
1
2
3
4
let t = 1, 2
div [] [
    button [ on.click (fun _ _ -> Client.TestTuple t) ] [ text "click me" ] 
]
.

The DocLens functionality works pretty well, but the example has several errors. This is a corrected and more complete version: http://try.websharper.com/snippet/user3359/0000Jz

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[<JavaScript>]
module HelloWorld =
    let title txt = Attr.Create "title" txt

    type Person = { Id: int; Name: string; Age: int }
    
    let people =
        Var.Create [
            { Id = 0; Name = "Ann"; Age = 34 }
            { Id = 1; Name = "Brian"; Age = 28 }
            { Id = 2; Name = "Clara"; Age = 43 }
        ]
    
    let getId            p = p.Id
    let newId           () = people.Value |> List.map getId |> List.max |> ((+) 1)
    let newPerson       () = { Id = newId(); Name = ""; Age = 0 }
    let insertPerson    () = people.Value <- newPerson() :: people.Value
    let appendPerson    () = people.Value <- people.Value |> List.append <| [ newPerson() ]
    let deletePerson id () = people.Value <- people.Value |> List.filter (getId >> (<>) id)
    
    let editPeople      () =
        people.DocLens(getId, fun vp ->
            form [] [
                Doc.Input             [] (Lens vp.V.Name)
                Doc.IntInputUnchecked [] (Lens vp.V.Age)
                Doc.Button "x"        [ title "Remove person" ] (deletePerson vp.Value.Id)
            ]
        )
        
    let Main = 
        div [] [
            Doc.Button "+" [ title "Insert person" ] insertPerson
            editPeople()
            text "----------------------- Again: -----------------------"
            editPeople()
            Doc.Button "+" [ title "Append person" ] appendPerson
        ]
        |> Doc.RunById "main"
By on 3/31/2018 5:40 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper