Developer Documentation. Learn more about WebSharper.

A quick walk-through to help you get started and learn about WebSharper.

Getting Started

Learn how to install, how to get started, and build your first application.

Install First app Pagelets

Web Abstractions

Check out how WebSharper makes your development project easier, faster and more robust.

UIs Piglets Sitelets

Cheat Sheets

Looking for a snippet that uses formlets or piglets? Check out the cheat sheets.

Formlets Piglets

Your first WebSharper application in 2 minutes


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
39
40
namespace Bundle1

open IntelliFactory.WebSharper
open IntelliFactory.WebSharper.Html
open IntelliFactory.WebSharper.Google.Visualization
open IntelliFactory.WebSharper.Google.Visualization.Base

[<JavaScript>]
module Client =

    let AreaChartData () =
        let data = new Base.DataTable()
        data.addColumn(ColumnType.NumberType, "Year") |> ignore
        data.addColumn(ColumnType.NumberType, "Sales") |> ignore
        data.addColumn(ColumnType.NumberType, "Expenses") |> ignore
        data.addRows(4) |> ignore
        [   [2004; 1000; 400]
            [2005; 1170; 460]
            [2006; 660; 1120]
            [2007; 1030; 540]   ]
        |> List.iteri (fun i yearData ->
            List.iteri (fun j value ->
                data.setValue(i, j, value)
            ) yearData
        )
        data

    let Main =
        Div []
        |>! OnAfterRender (fun container ->
            let visualization = new BarChart(container.Dom)
            let options =
                BarChartOptions(
                    width = 400,
                    height = 240,
                    legend = Legend(position = LegendPosition.Bottom),
                    title = "Company Performance")
            visualization.draw(AreaChartData(), options))
        |> fun el ->
            el.AppendTo "entrypoint"
Your first WebSharper application

Steps

Prerequisites: Nuget 2.7 or newer, Visual Studio 2010 or newer

  1. Install the Visual Studio extensions
  2. Create a new WebSharper Bundle Website project
  3. Add an Nuget reference to WebSharper.Google.Visualization
  4. Open Client.fs and add the code on the left
  5. Add an entry point <div id="entrypoint"></div>
  6. to your index.html in the body tag
  7. Hit F5 and see your app running
WebSharper templates in VS
Template All-F# Sitelet Client Server Remote
Applications
Sitelet Website
Sitelet Html App
Bundle Website
Helpers
Library
Extension
Sitelet Host Website

Application Templates


  1. Sitelet Website - a full client-server application implemented as a WebSharper sitelet.

    The sitelet uses a dynamic HTML template and placeholders (<div data-replace="placeholder" />, <div data-hole="placeholder" /> for HTML content, and ${placeholder} for string content) that are instantiated by the sitelet.

    See the HTML templates page for more information on dynamic templating.


  2. Sitelet Html App - a multi-page HTML/JavaScript application based on a sitelet.

    Similar to a Sitelet Website, this application also uses dynamic HTML templates and creates a set of HTML and JavaScript files that can be deployed in any HTML container.

    WebSharper mobile web applications can also be created from this template.


  3. Bundle Website - a single page HTML/JavaScript application with an HTML page and an F# source file that plugs content into it.

    The easiest way to get started with WebSharper: write a few lines of F#, add a placeholder for it in the HTML, and you are ready to go.

    See the "Your first app in 2 minutes" tab for an example.


Application Tiers


  • Client - Code compiled to JavaScript, executing on the client-side.

  • Server - Code you deploy for your application, executing on your server-side.

  • Remote - Code you from someone else's server, typically through a web service.

Nothing but F# in your applications

Write code in a single language, and generate your entire web app, including HTML5 and JavaScript automatically. WebSharper uses only a handful of attributes to drive code generation. Regular F# code without annotation is callable on the server-side only.

  1. [<JavaScript>] - marks functions or entire modules to be client-side. WebSharper will translate these code blocks to JavaScript.

  2. [<Rpc>] - marks functions to be callable from the client-side. WebSharper will generate code for each call automatically. No more callbacks - AJAX has never been simpler.

Crossing the client-server boundary

Client-server applications are modelled as WebSharper sitelets, generating HTML for both the server and the client side. Client-side functionality is embedded into server controls that can in turn be embedded in server-side markup:

1
2
3
4
5
6
type MyControl() =
    inherit Web.Control()

    [<JavaScript>]
    override __.Body =
        Client.Main() :> _

Once your sitelet is constructed, a simple declaration marks the containing assembly and enables seamless serving of your sitelet:

1
2
3
4
5
...
type Website() =
    interface IWebsite<Action> with
        member this.Sitelet = MySite
        member this.Actions = [Action.Home]
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
type Person = { Name: string; Age: int }

module Server =
    {{[<Rpc>]:RPC functions:This function is marked to be called remotely from the client and executes on the server.}}
    let GetPeople () =
        {{async:Asynchronous computations:You can mark computations to be asynchronous, these are executed without blocking the caller.}} {
            return [|
                { Name = "Alyssa P. Hacker"; Age = 29 }
                { Name = "Louis Reasoner";   Age = 45 } |]
        }

{{[<JavaScript>]:Client-side functions:Functions or entire modules can be marked to execute on the client.}}
module Client =
    let ShowPerson p =
        TR [TD [Text p.Name];TD [Text (string p.Age)]]

    let ShowPeople people =
        Table [
            THead [TR [TH [Text "Name"];TH [Text "Age"]]]
            TBody [ for p in people -> ShowPerson p ]
        ]

    let Main () =
        let out = Div []
        Div [
            out; Button [Text "Show People"]
            |>! OnClick (fun _ _ ->
                {{async:Asynchronous calls:Need to call asynchronous functions from the client? No problem, wrap it in an async block like if it was on the server.}} {
                    let! people = Server.GetPeople()
                    do out.Clear()
                    return out.Append(ShowPeople people)
                } |> Async.Start)
        ]

Compose Websites

With WebSharper Sitelets , the server-side is also in for an upgrade in composability and maintainability!

  • Use the same combinators to write static markup and dynamically inserted content.

  • Use type-safe URLs to eliminate dead internal links and get the compiler to help you easily propagate any change in the URL scheme.

  • Simply compose together sub-websites.

  • Use this mechanism both for HTML content and REST APIs in JSON or XML.

  • Integrate Sitelets pages alongside a legacy ASP.NET or ASP.NET MVC application.

  • Optionally, create a static website by generating a set of HTML files.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
type {{Action:Type-safe URLs:The action type represents all URLs provided by the application. Internal links are inserted using values of this type instead of strings. Whenever you change your URL scheme, the compiler will point you to all the links that need to be changed!}} =
    | Index
    | BlogEntry of int
    | ...

let BlogEntryContent entryId =
    Content. {{PageContent::This action returns HTML content. Another possibility is `CustomContent`, for example to return JSON as a REST API.}} (fun ctx ->
        { Page.Default with
            Title = Some ("Blog entry number " + string entryId)
            Body =
                [
                    A [HRef {{(ctx.Link Index)::This is how you insert an internal link, guaranteeing that you're not making a typo in a string and providing you with IntelliSense completion.}}] -< [Text "Go to Index"]
                    RenderBlogEntry entryId
                ]
        })
...
let {{MySite::Websites are first-class, composable values.}} =
    {{Sitelet.Infer::This function will build a site whose URLs are automatically inferred from the action type. In this case, the inferred URLs are `/Index`, `/About` and `/BlogEntry/42`. But if you want, you can also write your own URL parser and still take advantage of the `ctx.Link` mechanism!}} (function
        | Index -> IndexContent
        | BlogEntry id -> BlogEntryContent id)
        | ...

Compose UIs Like a Pro

Writing interactive user interfaces is often a repetitive and error-prone chore. WebSharper provides powerful abstractions that deal with many of these details, and let you concentrate on your code instead.

Use WebSharper Formlets to declaratively construct interactive client-side forms and wizards with input validation and other goodness, quickly. No need to type any HTML, it is generated for you!

1
2
3
4
5
6
7
8
9
10
11
12
type Species = Cat | Dog | Piglet
type Pet = { species: Species; name: string }

Formlet.Return {{(fun s n -> { species = s; name = n })::Define how user input is combined into more complex data.}}
<*> {{Controls.RadioButtonGroup::The first field is a list of radio buttons. See how easy it is to define the (correctly typed!) value returned for each option.}} {{(Some 1):By default, select field number 1 ("dog").}} [ "cat", Cat
                                         "dog", Dog
                                         "piglet", Piglet ]
<*> (Controls.Input "Fluffy"
    |> {{Validator.IsNotEmpty::Declare what the input data should look like, and Formlets will check it for you.}} "Please enter the pet's name."
    |> Enhance.WithValidationIcon)
|> Enhance.WithSubmitButton
|> {{Formlet.Run::Perform an action on submit. Here we just show the user what they just typed, but we could for example send the data to the server.}} (fun pet -> JavaScript.Alert ("Hi, " + pet.name + "!"))

Piglets


Alternately, you can use WebSharper Piglets for finer-grained control over the exact markup.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Piglet.Return {{(fun s n -> { species = s; name = n })::Just like with Formlets, define how user input is combined into more complex data.}}
<*> {{Piglet.Yield::However, don't tell it to render this field as a radio button; we'll create it ourselves.}} Dog
<*> (Piglet.Yield "Fluffy"
    |> Validation.Is Validation.NotEmpty "Please enter the pet's name.")
|> Piglet.WithSubmit
|> Piglet.Run (fun pet -> JavaScript.Alert ("Hi, " + pet.name + "!"))
|> {{Piglet.Render::Now we can define the exact markup to use to render this Piglet. We can even have several render functions for the same Piglet, for example for a mobile version.}} (fun {{species name submit::These represent the varying values of each field. You can then associate them with controls such as input fields and WebSharper will keep them synchronized.}} ->
    Form [
        {{Controls.Radio:Piglet Controls are simple elements that you can style and compose at will.}} species [ Cat, "cat"
                                 Dog, "dog"
                                 Piglet, "piglet" ]
        Div [ Controls.Input name -< [Attr.Class "name-input"] ]
        Div [ Controls.Submit submit ]
    ])

Use JavaScript Libraries

  • Use jQuery, Ext JS, Kendo UI, Google Maps, O3D, and many more libraries using WebSharper extensions .

  • Enjoy type-safe access with code completion. Easy definition of inlined JavaScript code when necessary.

  • Your library not listed? Quickly build your own binding directly or use our Interface Generator DSL.

  • Automatically include dependencies by simply using a library in your WebSharper project, having WebSharper pull together all required scripts and CSS files via the Resource system .

  • Consider contributing new libraries to the community by releasing on NuGet .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
open IntelliFactory.WebSharper
open IntelliFactory.WebSharper.Html
open IntelliFactory.WebSharper.JQuery

[<JavaScript>]
module Client =

    let Main () =
        let panel = Div [Text "Panel"]
        Div [
            panel
            Button [Text "Toggle Panel"]
            |>! OnClick (fun _ _ ->
                {{JQuery.Of:jQuery:Use jQuery with code completion.}}(panel.Body).Toggle().Ignore)
        ]

Interface with TypeScript

WebSharper makes it easy to interface with TypeScript both ways:

  • It outputs TypeScript type declarations for all generated JavaScript code, including for WebSharper extensions.

  • It can read TypeScript type declarations to generate WebSharper extensions automatically, so you can use virtually any JavaScript library for which such declarations are available.

Here is how easily you can work with a new external JavaScript library:

1
2
3
open IntelliFactory.TypeScript

type PhoneJs = Generator<"typescript/phonejs.d.ts">

Browse the entire documentation