NemerleWeb

Preface

NemerleWeb is based on Nemerle language. If you are not familiar with this language, it is similar to C# but easier to learn and more powerful.

You can write code in any language providing front-end for Nemerle. For example, there is a C# front-end implemented, we will show it further in this tutorial.

About NemerleWeb

NemerleWeb is Model-View-ViewModel framework that simplifies creating dynamic web pages. You write your code in Nemerle or other front-end language like C#, then it gets translated into mixture of javascript, HTML and server side classes. Basic page looks something like this:

This sample displays input box that when changed, automatically updates div contents.

Since we can't bind values to part of text node, framework creates empty element and binds value to that.

Binding

Usually, when you develop your web pages, there is some data you want to display and update. Most popular example of that functionality is probably ToDo List. You start with empty collection of tasks. Now you want to add something, that means you will have to modify your collection. You can do it in jQuery fashion:
$("button").click(function() {
   $("ul").append($("<li>" + $("input").text() + "</li>"));
   $("input").text("");
});

And while this code looks simple enough, it has it's flaws. First of all it's highly jQuery specific. You are not operating inside your problem domain, which is ToDo List, but rather dealing with DOM structure and events.

If this is the only thing your application does, then it's probably fine. But as your project grows you will find, that maintaining this kind of code is not that easy.

Secondly, this code contains 3 references to DOM: "button", "ul", "input". Again, as soon as you face the need of refactoring you will have to deal with these string based references, which means lots of Ctrl+F'ing.

Third, and probably most important issue is lack of data structure. As of this moment, all your data lives inside DOM, so you can't make queries against it, or modify in anyway. To do that, you will again need to traverse document, and build your model piece by piece.

So, how can we deal with these problems? This is where MVVM and specifically Binding will help us. MVVM by it's nature advertises decoupling model from presentation level. What that means, is that you can have your domain model with entities like Task, User or Milestone, that know nothing about HTML, WPF or any other presentation engine.

Now let's try and implement this sample with NemerleWeb:

Note: That upper part doesn't know anything about HTML. It is like any other code that you write. There is a collection of tasks, and code can modify it in some way. For example if we need to search for tasks, all we need to change is:

<ul $foreach(t in Tasks.Where(t => t.Contains(SearchTerm)))>
where SearchTerm is new field binded to text input. If this field is modified, task list will modify itself, without any need to re-render it manually.

Not only this is easier to write, but it is also much easier to maintain. What will happen if you decide that Task is not just a string, but also contains Date, Priority, Status or other fields. I assure you, that jQuery version will eventually grow into something huge and almost unreadable.

To do it properly we need to introduce Task type.

[Record]
class Task
{
   Title : string;
   Priority : int;
   Status : bool;
}

How will our code change? Actually not that much:

It still looks like normal code, nothing framework'y here. Actually, one of the goals of this project was to introduce as few new concepts as possible, and yet give developers ability to express themselves without restrictions.

Look, for example at HTML. Can you notice any "binding" primitives, that tell you that data is binded and not statically rendered? There is none - you write your markup just as you write any other template, be that Razor, Haml or anything else. It's framework's job to parse it and create appropriate bindings, so it all happens behind the scenes.

Client-side logic

Alright. You know the basics of NemerleWeb and how it works. Let's dive into more complicated examples. Did you notice

<ul $foreach(t in Tasks.OrderBy(t => t.Priority))>
line in previous example? It shows how easy it is to add new features, like ordering, when you keep your model separately from view.

Now, let's do something fun, like client-side validation. There are numerous validation frameworks out there. Some of those are based on specific attributes, other on specific classes. Web frameworks like ASP.NET MVC or Ruby on Rails try their best to generate all that meta information inside your template. What if validation was much simpler than that?

Let's see how will very simple validation look:

Easy. But attentive web developer will notice, that there is no specific messages for different validation problems. Let's fix that:

I hope, this sample illustrates my previous comment about one of the goals being not to introduce new concepts without actual need. Also, keep in mind, that while we created methods that accept Task, we could also move validation logic into model itself, or even different type. It means that we would have the same validation methods on server and client side. No need to duplicate your validation logic or rely on some engine to generate HTML that might not suit your requirements. Everything is under your control.

Communication with server

There is no serious web application without contacting the server. So, how do we do this?

Lets define Server class inside our Unit:

HTTP servers are stateless by their nature, so each request will create new Server object. That means, that if you want to share data between requests you should store it somewhere. The easiest way is to store it in "static" variable (all multithreading issues apply here). Of course usually you will be using database to save or retrieve data.

As soon as you define Server class, you are able to use it as an instance via "server" field. This field is created automatically by macro, so you don't need to declare it yourself. "server" methods have the same signature as Server class, but with additional callback, which is called after server response. Example:

server.GetName(name => DisplayName(name));

This simple code demonstrates sending and receiving data from server. Of course this sample rather trivial, but look how easy it was to implement communication. You don't need any special proxy classes, anything unrelated to the work itself.

C#

What about writing in C# if you don't want people to learn new language? No problems. Nemerle supports different front-ends, you can implement your own, e.g. F# front-end. Just write code in C#, put .cs extension of course, and add file to the project.

Note: It is not fully compatible C# language. It is being translated to Nemerle to support some features like macro-attributes. Also there are some unsupported C# features like dynamic (By the time writing this tutorial).

Let's rock:

Nemerle syntax macros cannot be used in C# program. If you need them you can create a partial class, one part in C# and the other in Nemerle (yes it works). In the future there will be alternative syntax using macro attributes, and you won't need partial classes.

Templates

One important feature, that was left unnoticed is Templating. Imagine, that you are developing some kind of Contact List application. Each contact has first name, last name, photo, telephone number etc. Let's put it into code:

[Record]
class Contact
{
  FirstName : string;
  LastName : string;
  PhotoUrl : string;
  PhoneNumber : string;
  Email : string;
}

Now, to render all that we need quite a bit of HTML:

<#
  <div class="contact">  
    <div class="left">
      <div class="photo">
        <img src="$PhotoUrl" />
      <div>
    </div>
    <div class="right">
      <div class="firstname">$FirstName</div>
      <div class="lastname">$LastName</div>
      <div class="phone">$PhoneNumber</div>
      <div class="email">$Email</div>
    </div>
  </div>
#>

This kind of HTML is highly specific for contacts and not that usable for anything else. So why should we include it in Contact List unit? By doing that, we are creating God object, that has too many responsibilities, and is hard to maintain. Much better choice would be to move this HTML where it belongs, to Contact class:

[Record, Unit]
class Contact
{
  FirstName : string;
  LastName : string;
  PhotoUrl : string;
  PhoneNumber : string;
  Email : string;

  public View() : string
  {
    <#
      <div class="contact">  
        <div class="left">
          <div class="photo">
            <img src="$PhotoUrl" />
          <div>
        </div>
        <div class="right">
          <div class="firstname">$FirstName</div>
          <div class="lastname">$LastName</div>
          <div class="phone">$PhoneNumber</div>
          <div class="email">$Email</div>
        </div>
      </div>
    #>
  }
}

Now, we can define Contact list class:

[Unit]
class ContactList
{
  Contacts : List[Contact];

  public View() : string
  {
    <#
      <div $foreach(contact in Contacts)>
        <div template="$(template(contact))" />
      </div>
    #>
  }
}

Template attribute will automatically look for View method inside the object it receives as an argument and renders it. If you have defined multiple methods or use another naming convention, you can pass method name as a second parameter. Full list of different ways to render a template looks like that:

<#
  <ul>
    <li><span template="$(template(_.Dummy))"></span></li>
    <li><span template="$(template(_.Dummy, GetCustomViewName("1")))"></span></li>
    <li><span template="$(template(_.Dummy, _.CustomName))"></span></li>
    <li><span template="$(template(_.Dummy, _.CustomName()))"></span></li>
    <li><span template="$(template(Dummy))"></span></li>
    <li><span template="$(template(Dummy, "CustomName"))"></span></li>
    <li><span template="$(template(Dummy, GetCustomViewName("2")))"></span></li>
    <li><span template="$(template(Dummy, _.CustomName))"></span></li>
    <li><span template="$(template(Dummy, _.CustomName()))"></span></li>
  </ul>
#>

where Dummy is a member of containing class and defined as follows:

[Unit]
public class TemplateDummy 
{
  public GetCustomViewName(suffix : string) : string
  {
    //That won't work, because we don't have "View1" or "View2" defined
    //But this feature is very usable, when you need your template to depend on variable
    "View" + suffix; 
  }

  [Html]
  public View() : string
  {
    <#
      <span>
        Passed (View)
      </span>
    #>
  }
  
  [Html]
  public CustomName() : string
  {
    <#
      <span>
        Passed (CustomName)
      </span>
    #>
  }
}   

JavaScript Typing

NemerleWeb allows to type arbitrary JavaScript code. You write regular Nemerle code, but it doesn't translate as usual code in NemerleWeb.

Assume we want to call window.alert. The simplest method is using js macro to write JavaScript as-is;

js <# window.alert("hello"); #>

While this approach is simple it doesn't validate your code. You can easily write a typo and the page will be incorrect . After all the purpose of NemerleWeb is to write type safe code.

This can be done by writing simple class:

class window
{
  public assert(str : string) : void {}
}

While this is obvious , it doesn't work.

NemerleWeb doesn't generate simpe JS code in order to have method overloads and ober type safety. You'll have the following JS ( more or less ): window.alert["System.String"]("abc") But we wanted simple window.alert("abc") :-(

Don't worry, you don't need to rewrite anything, just use special attribute JSApi.

JSApi

Add attribute "JSApi" to your class and you get 'normal' names in JS.

[JSApi]
class window
{
  public static alert(s : string) : void {}
}

That's all. JSApi improvement The better code is to disallow calling this class in the server side:

[JSApi]
class window
{
  public static alert(s : string) : void { throw NotImplementedException(); }
}

JSApiImpl

To simplify our life there is a macro JSApiImpl. This macro adds JSApi attribute automatically.

[JSApiImpl]
class window
{
  public static alert(s : string) : void;
}
Attention: you don't need to write the body at all!

JSApiRoot

In order to specify which parts of the fully qualified name are not relevant in JS generation, there is a special macro JSApiRoot. Usage:

[assembly: JSApiRoot("MyNamespace")]

Then later in code you can write anything inside MyNamespace and 'MyNamespace' won't appear in JS:

namespace MyNamespace
{
  [JSApi] class A { }
}

def a = MyNamespace.A(); // Resulting JS: var a = new A();

JSCall and JSNew

JavaScript allows many things that are not placed good in Nemerle type system. For instance one can define function that returns different types for different arguments and even works with 'new' ! Code sample:

function F(a) {
  if(this == window)
    if(typeof a === "number" ) return 1;
    else return "a";
  else {
   this.X = 1;
  }
}

How you type that? You must have a type with both constructor and call a.k.a '()' operator. To workaround this problem NemerleWeb introduces special syntax for defining typing and for calling:

[JSApiImpl]
public interface F_X
{
  public X : int { get; set; }
}

[JSApiImpl]
public interface F_Type
{
  [JSCall]
  public static @_(a : int) : int;

  [JSCall]
  public static @_(a : object) : String;

  [JSNew]
  public static @_() : F_X;

  [JSNew]
  public static @_(a : object) : F_X;
}

[assembly: JSApiRoot("M")]

module M
{
  public F : F_Type;
}

// ---
using M;

[Unit]
class MyUnit
{
  public X() : void
  {
    def a = jscall F(1);   // var a = F(1);
    def b = jscall F("x"); // var b = F(x);
    def c = jsnew F();     // var c = new F();
    def d = jsnew F(1);    // var d = new F(1);
  }
}

This way you can handle RegExp class which defined both as callable (RegExp("a")) and as constructible (new RegExp("a")). Also solves problem with jQuery which can used as $(document) and as $.method() .

Note: In most cases the code is simpler and one can define simple class with constructor and @() operator, also automatic code generation from TypeScrip can do it. Maybe it will be done in the future.

Integration with TypeScript

NemerleWeb supports automatic typing through TypeScript Declaration files (.d.ts).

The usage is following:

[assembly: GenerateTypedJS(
  Root = "Your root namespace/module",
  Lib = "Optional path for library infrastructure (lib.d.ts) file",
  // List of tuples
  // First argument is directory.
  // Second optional argument is excluding pattern (RegExp).
  Files = [ ("TS", @"TS\\(_infrastructure|i18next\\lib)\\") ]
)]
Important: This macro implies JSApiRoot macro, you don't need to repeat yourself.

There is an special assembly NemerleWeb.TypedJS ready with most of typing you'll need.