More Advanced Features

This page introduces some of the more advanced features of Bellevue

Templates

Templates are mostly used when you need to apply some HTML to each element of a collection. In Web Forms pages this replaces the need for a repeat loop ("/Views/Demo/Demo2_Intro_WebForms.aspx"):

<div class="productList">
    <%
        foreach (string name in (string[])ViewData["AllNames"])
        {
    %>
        <div><a href="/demo/Demo2_Intro_Bellevue/<%= name %>"><%= name %></a></div>
    <% 
        }
    %>
</div>

Note that you can apply a template also to a single item, but this is currently less useful. In future versions, conditional and inline templates would make it more justified scenario.

You start with templates by defining a template with @template directive ("Demo2_Intro_Bellevue.bvue"):

@template productListTemplate "#leftArea .productList div"
{
    a        
    {
        text:   item(); 
        attr:   href concat("/demo/Demo2_Intro_Bellevue/", item());
    }
}

The first parameter is the ID of the template (nothing to do with the html ID) and second parameter is the selector that finds the template in the HTML. Matched element(s) will be taken away from the original HTML and used only when apply-template is called.

Within the template, you may have rule sets that are specific to the template. In this case text and href-attributes within the template are modified. You could also call apply-template within template, so nested templates are possible. The "item()" function returns the item to which the template is bound to when the collection is looped through.

In this case the selector matches this HTML ("Demo2_Intro_Bellevue.html"):

<div class="productList">
    <div><a href="/linkHere">Product 1</a></div>
    <div><a href="/linkHere">Product 2</a></div>
    <div><a href="/linkHere">Product 3</a></div>
</div>

All the inner divs are taken as templates and applied one after each other. In this case, they are all the same, but they could also have different HTML e.g. if you want even and odd rows to be with different colors.

To apply the HTML, you use the apply-template declaration:

#leftArea .productList {   apply-template: data(AllNames) productListTemplate }

In the next preview version, the template syntax should clearly have much more options. I already have much of the plumbing ready, but I need to check exactly how to implement the syntax. The idea is to add the following features:

Also, the most important feature missing in the current implementation is the possibility of defining new attributes as you call templates: So that you have reusable template that always need parameters "item(link)" and "item(label)" and when calling the template you could specify e.g. "link=item(url), label=item(text)". I am having a bit of trouble in figuring out a good syntax that would be compatible with CSS syntax, but it will be there - I promise.

So with templates there are many features missing in the current version. This is the biggest undercon area. But I hope you get the idea of the potential power: It is very easy to make repeating table rows and other sections with just a few lines of code. Much easier than with Web Forms.

Master pages

Master pages are Web Forms specific: there is no Asp.Net MVC standard way of plugging into them. So each view engine typically creates their own master pages system. In Bellevue, you define a master view by using the @master directive ("/Views/Shared/Site_Master.html"):

@master
{
    #mainContentPlaceholder
    {
        placeholder-id:     main;
    }
    title
    {
        placeholder-id:     title;
    }
    #pageStyles
    {
        placeholder-id:     styles;
    }
}

Selector can be any valid selector that matches HTML - in fact even several elements is possible. ID's must be unique. In addition, you can have normal Bellevue rule sets to add active content to master page HTML.

You use the master view in an individual view using @master-is directive ("Demo3_UseMaster.html"):

@master-is Site_Master
{
    body    { placeholder: main; }
    title   { placeholder: title; }
    
    /*  When page is called with "?useAnotherMaster=true",
        the value "Site_Master" above is overriden by controller */
}

Body and title in the above example could be any selectors within the page. So the page can be a full HTML page, which can be rendered stand-alone, but when applied to a master page certain parts of it are extracted (examples are like that).

You can switch the master page in controller, like you would do with Web Forms (see Demo controller action "Demo3_UseMaster" for example).

I am pretty happy with the master view concept as it is. Only things I am considering adding is automatic support for title, styles and scripts both in the head and as last elements in body. Another thing is that at the moment, if no content is added to a placeholder, the HTML inside the placeholder is rendered, but no active stuff is applied - this will be fixed using templates.

@if directive

The current implementation also supports the @if directive. There is no example in the demo project, but you use it basically like this:

@if data(IsAuthenticated) {
    #userName   { text: data(userName);                  }
    #buttons    { render-control-add: logOffControl;    }
}

The reason I am not advertising it much yet is that I am not quite sure yet how to support else and else-if cases, so I will need to rethink this syntax. For many cases, you can also use the "if()" data function, which has the else functionality and even else-if by nesting functions.