Developer Documentation. Learn more about WebSharper.

A quick walkthrough to help you get started and learn about WebSharper.

Getting Started

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

Learn more

Basics

Learn how WebSharper makes your web development easier, faster and more robust.

Learn more

Web Abstractions

Learn how WebSharper makes your web development easier, faster and more robust.

Learn more

Cheat Sheets

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

Formlets Piglets

Getting Started with WebSharper



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
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"

In CloudSharper

Your first WebSharper application

In Visual Studio

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

Your first WebSharper application
  1. Install the Visual Studio extensions
  2. Create a new WebSharper "Single-Page Application" 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 before the script link
  7. Hit F5 and see your app running

Installing WebSharper into Visual Studio

Developing with WebSharper in Visual Studio currently requires:

Important : Note that Visual Studio 2012 may ship with an outdated version of the NuGet Package Manager. Please go to "Tools > Extensions and Updates" and make sure that the latest version is installed (at least NuGet 2.7).

When your environment is ready, download and install the main WebSharper .vsix file from the WebSharper download page . This will install the WebSharper project templates into Visual Studio (you may have to restart Visual Studio if you have it running while you install WebSharper), making it easy to get started with new projects.

Updating WebSharper in existing projects

When you create a new WebSharper project from a Visual Studio template, it will use the version of WebSharper that came bundled with the Visual Studio installer you used.

WebSharper extensions, as well as the core WebSharper binaries, are distributed via Nuget. This means that you can upgrade WebSharper in or add WebSharper extensions to your existing Visual Studio projects by using the NuGet package manager, as you would with any other Nuget package.

Visual Studio templates

Once you installed WebSharper and, if needed, restarted Visual Studio, you should see the main WebSharper templates in the New Project dialog.

WebSharper templates in VS

Main Application Templates

The three main WebSharper application types are:

  1. Client-Server Application - 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. HTML Application - 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. Single-Page Application - 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.

Inner working

This table summarizes the capabilities of the available application/helper project templates:

Template All-F# Is Sitelet? Client Server Remote
Applications
Client-Server App
HTML App
Single-Page App
Helpers
Library
Extension
ASP.NET Container

Application Tiers

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

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

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

WebSharper Basics



Constructing client-side markup

The various client-side DOM constructors, used in virtually all WebSharper applications, are in the IntelliFactory.WebSharper.Html namespace. The general syntax is as follows:

HTML

WebSharper

<br />

Br []

<span class="c1" />

Span [Attr.Class "c1"]

<p>Text here</p>

P [Text "Text here"]

<div class="c1">...</div>

Div [Attr.Class "c1"] -< [...]

Binding events to DOM nodes

You can bind to various DOM events such as mouse ( Click , DblClick , etc.) and keyboard events ( KeyDown , KeyPress , etc.) easily by applying OnXXX on the target DOM node:

1
2
3
4
open IntelliFactory.WebSharper.Html

{{Button:HTML combinators:These HTML-like combinators generate DOM nodes.}} [Text "Click me!"]
|>! OnClick (fun e args -> e.Text <- "Hello!")

Constructing server-side markup

Server-side HTML constructors are in the IntelliFactory.Html namespace and are typically used with client-server applications. The general syntax is roughly equivalent to the client-side markup language.

You can attach event handlers to server-side markup or include dynamic client-side content or behaviour, by declaring ASP.NET-style server-side controls whose bodies are expressed as client-side markup:

1
2
3
4
5
6
7
open IntelliFactory.WebSharper

type MyControl() =
    inherit Web.Control()

    [<JavaScript>]
    override this.Body = ...

You can then embed these server-side controls directly into server-side markup, bringing the desired client-side behavior:

1
2
3
4
5
6
open IntelliFactory.Html
open IntelliFactory.WebSharper

{{Div:Server-side markup:This is a server-side HTML combinator: note the open namespace declaration.}} [Class "my-class"] -< [
    Div [new MyControl()]
]

Coding 100% F#, no JavaScript

Client-server applications are modelled as WebSharper sitelets, generating HTML for both the server and the client side. A handful of simple attributes decide how your applications are generated. Regular F# code without annotation is callable on the server-side only.

  1. [<Rpc>] - marks functions to be callable from the client-side. WebSharper will generate code for each call automatically. No more explicit callbacks or having to deal with data conversion - Ajax has never been simpler.
  2. [<JavaScript>] - marks functions or entire modules to be client-side. WebSharper will translate these code blocks to JavaScript.

Crossing the client-server boundary

Server calls become simple F# function calls, type checked statically:

1
2
3
4
5
6
7
8
9
10
[<Rpc>]
let {{GetUserData:RPC functions:This function is marked to be called remotely from the client and executes on the server.}} username =
    Database.RetrieveUserData username

[<JavaScript>]
let ShowUserData username =
    async {
        let! data = GetUserData username
        DisplayUserData data
    }

Communicate with data of any shape

You can pass complex data structures, and share data types between client and server to ensure a consistent and reliable communication and execution - WebSharper takes care of the rest by seamlessly converting to and from JSON.

Currently, any list/array/map/set of records or discriminiated unions of any primitive and common composite types (such as DateTime ) are supported, and can be passed between server and client in both directions.

Seamless Asynchronous Communication

Discover the joy of F# asynchronous workflows , making it straightforward to write correct, readable and entirely non-blocking code, on both the server and the client.

Asynchronous computations may take an arbitrarily long time to complete. You can avoid busy waiting in your caller operation by defining your computation as an asynchronous workflow and calling it asynchronously using let! .

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>]
    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:Comprehensions:Powerful sequence/list/array comprehensions to generate elements.}} p in people -> ShowPerson p ]
        ]

    let Main () =
        let out = Div []
        Div [
            out; Button [Text "Show People"]
            |>! OnClick (fun _ _ ->
                async {
                    {{let!:Asynchronous calls:Just like their server-side equivalent, client-side async calls are non-blocking.}} people = Server.GetPeople()
                    do out.Clear()
                    return out.Append(ShowPeople people)
                } |> Async.Start)
        ]

Powerful Web Abstractions



WebSharper UI.Next
a reactive foundation for your apps


Learn more

Single Page Applications

Familiar with Angular.JS? Now you can do better!

Reactive DOM

Familiar with React? Construct DOM elements that react to changes.

Observable collections

It has never been easier to bind your models and views together.

Animations

Mobile friendly reactive animations and transitions.

Compose Websites

With 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 your URL scheme.

  • Simply compose sitelets together into larger ones.

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

  • Integrate sitelets alongside a legacy ASP.NET or ASP.NET MVC application.

  • Create static websites 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 entry points to a sitelet-based application, accessible via various HTTP commands such as GET or POST. Internal links to the various pages are inserted using values of this type instead of strings.}} =
  | Index
  | {{[<CompiledName "entry">]:Custom automatic URLs:You can override the inferred URL for a given entry point this way.}} 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):Safe URLs:This is how you insert an internal link, guaranteeing that you're not making a typo in a string and providing you with handy code completion.}}] -< [Text "Go to Index"]
           RenderBlogEntry entryId
         ]
    })
...
let {{MySite:Sitelets:Sitelets are first-class, arbitrarily composable web application values.}} =
  {{Sitelet.Infer:Building URLs schemes:This function will build a site whose URLs are automatically inferred from its action type. In this case, the inferred URLs are `/Index` and `/entry/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)
    | ...

Putting your sitelet together

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]

The way UIs should be composed

Writing interactive user interfaces is often a repetitive and error-prone chore. WebSharper provides powerful abstractions that deal with many of these details, and lets 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 p -> JavaScript.Alert ("Hi, " +p.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 name.")
|> Piglet.WithSubmit
|> Piglet.Run (fun p -> JavaScript.Alert ("Hi, " +p.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 ]
    ])

Going further



Go Mobile

  • Reach millions of mobile devices by leveraging future-proof HTML5.

  • Package HTML5 WebSharper apps into native mobile applications for Android, iOS and Windows Phone using WebSharper.Mobile .

  • Extensions available for mobile-friendly libraries, including jQuery Mobile and Sencha Touch.

  • Use the same straightforward client-server communication of WebSharper as in websites.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{{ExtCfg:Typed Sencha Touch config objects:Generated automatically from official documentation}}.Container(
    Fullscreen = true,
    Layout = "fit",
    Items = [|
        ExtCfg.TitleBar(
            Docked = "top",
            Title = "Sencha Touch with WebSharper"
        )
        ExtCfg.dataview.List(
            ItemTpl = "{title}",
            Data = [| {{for:Powerful syntax: Use F#'s array expressions and more}} i in 1 .. 10 -> {{New:Construct JS objects:Translates to JavaScript object literal}} ["title", string i] |]
        )
        ExtCfg.Toolbar(
            Docked = "bottom",
            Items = [|
                ExtCfg.Button(
                    Text = "Say hello",
                    Handler = fun() -> Ext.Msg.Alert("", "Hello World!")
                )
            |]
        )
    |] : ExtCfg.Component[]
).Create()

Simple apps in just a few lines of code


Sencha Touch app


Learn More

Run F# Everywhere

F# is a functional-first programming language helping you tackle any problem with concise and correct code.

Compile F# code to JavaScript/HTML5 applications with WebSharper to leverage the F# advantage everywhere - whether it is client code running on mobile and desktop browsers, backend logic on the web server, or analytics in the datacenter. F# can do it all.


fsharp.org Testimonials Samples

F# and WebSharper in Action


1
2
3
4
5
6
7
type {{Person:Types:Type definitions fit a single line.}} = { Name: string; Age: int }

{{[<JavaScript>]:JavaScript:The entire module is compiled to JavaScript by WebSharper.}}
module Client =

    let DisplayName {{p:Type Inference:The type of p is inferred.}} =
        JavaScript.Alert("Person: " + p.Name)

F# Advantages:


Functional Programming Trends


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