Mini-tutorial: client-server widgets

This short tutorial is an example of client-server Eliom application. It gives an example of client-server widgets.

It is probably a good starting point if you want to learn quickly how to write a client-server Eliom application with a short example and few explanations. For more explanation, see the "graffiti" tutorial or read the manuals.

The goal is to show that, unlike many javascript libraries that build their widgets programmatically (by instanciating classes or calling functions), Eliom makes possible to generate page widgets on server side, before sending them to the client. Thus pages can be indexed by search engines.

This tutorial also shows that it is possible to use the same code to build the widget either on client or server side.

We chose a very simple widget, than could be the base for example for implementing a drop-down menu. It consists in several boxes with a title and a content. Clicking on the title opens or closes the content. And it is possible to group some of the boxes together to make them behave like radio buttons: when you open one of them the previously opened one are closed.

screenshot

First step: define an application with a basic service

The following code defines a client-server Web application with only one service, registered at URL / (the root of the Web site).

It also defines a client side application (section {client{ ... }} ) that appends to the page a widget, generated on client side.

{shared{
  open Eliom_content
  open Html5
  open Html5.D
}}

module Ex_app =
  Eliom_registration.App (struct let application_name = "ex" end)

let _ =
  Ex_app.register_service ~path:[] ~get_params:Eliom_parameter.unit
    (fun () () ->
      Lwt.return (Eliom_tools.D.html ~title:"ex" ~css:[["css"; "ex.css"]]
                   (body [h2 [pcdata "Welcome to Ocsigen!"]])))


{client{

  let mywidget s1 s2 =
    let button  = div ~a:[a_class ["button"]] [pcdata s1] in
    let content = div ~a:[a_class ["content"]] [pcdata s2] in
    div ~a:[a_class ["mywidget"]] [button; content]

  let _ =
    lwt _ = Lwt_js_events.onload () in