Views and Layouts

Ejscript views are HTML pages with embedded JavaScript code. Views are created by merging content pages with a layout page to create composite pages that resemble what the user will actually see. The composite pages are rendered by Controllers after they have finished processing the requested Action. The view pages are processed by Ejscript, the code is run and a final HTML page sent to the client.

JavaScript code embedded in your web pages enables dynamic data to be inserted at runtime into what would otherwise be static web pages. Ejscript provides a set of directives to make it easy to refer to single JavaScript variables, expressions or code blocks in your web pages. A suite of Ajax View Controls provides high level components such as tables, charts, tabs, and forms that are Ajax-enabled for a seamless dynamically updating user experience.

Layouts — Creating a Consistent Look and Feel

A web application typically consists of many web pages that share a common look and feel. Usable applications have a consistent structure, menus and appearance so the user can easily navigate that application. However, designing and maintaining that consistent look and feel is frequently quite difficult.

Layout Pages

The Ejscript web framework provides a templating layout engine so that each page can reuse a common layout page and not have to repeat the common application UI elements in each page. Ejscript does this by automatically merging layout pages and content pages to create a composite page that matches what the user actually will see.

For example: this is a layout page called "layouts/default.ejs" which defines the top level HTML content for all content pages. It has a banner image and division tags that structure the page:

<html>
<body>
    <div class="top">
        <img src="banner.jpg" />
    </div>
    <div class="content">
        <%@ content %>
    </div>
</body>
</html>

Modifications to this page, will be reflected automatically in all content pages.

Content Pages

A content page defines only the HTML and code that is different for a specific page. It is merged with a layout page by inserting the content and replacing the <%@ content %> tag in the master page.

For example, consider the content page named "views/Demo/index.ejs":

<h1>Content Page</h1>
<p>Hello World</p>

This would render a composite web page back to the user:

<html>
<body>
    <div class="top">
        <img src="banner.jpg" />
    </div>
    <div class="content">
        <h1>Content Page</h1>
        <p>Hello World</p>
    </div>
</body>
</html>

Alternate Layout Pages

A content page can request a specific layout page by using the <%@ layout "file"> directive.

<%@ layout "alternateLayout ">
<h1>Content Page</h1>
<p>Hello World</p>

This instructs the templating engine to use the "alternateLayout.ejs" file rather than the default layout. The default layout page is called "layouts/default.ejs".

Multiple Layout Pages

You are not restricted to a simple two level layout and content page scheme. A layout page can itself refer to another layout page to gradually build up the application's look and feel. To do this, the layout page needs to include an explicit <%@ layout "file"> directive.

Development Time

The combining of layout and contents pages occurs at development time, as does the compilation of the composite page into byte code. At run-time, all that remains to be done is actually execute the byte code and substitute dynamic data into the page. This results in the fastest run-time execution because the layout processing and page compilation occur only once and at development time.

Directory Structure

Ejscript follows the Convention over Configuration design paradigm where developers only need to specify the unusual parts of their application. This is exemplified by an expected directory structure for views and layouts.

layouts
  |
  + Layout pages...
views
  |
  |
  + ControllerName
         |
         + View pages...

The mvc application generator program will create these directories for you when you run

mvc generate appName

After creating the application, you should place all content views for a controller under the "views/ControllerName" directory. The "ControllerName" directories should by convention begin with an upper case letter. The "views" and "layouts" directories are lower case.

Static Web Content

Static web page content such as images, CSS pages and other similar content should be placed under the web directory. While this content can be served by the Ejscript handler, it should ideally and optimally be processed directly by the web server. The Ejscript module for Apache and Appweb will enable this automatically. If you are using the CGI or FastCGI for hosting Ejscript, you may wish to configure your web server to serve these pages directly.

Stand-Alone Ejscript Web Pages

Not all Ejscript web pages are views. You can create stand-alone Ejscript web pages. These do not use layout pages and do not have access to Models, Controllers or View objects. Why create stand-alone Ejscript pages you ask? Because it is sometimes convenient to have a little bit of scripting inside a mostly static HTML page.

For example: This will insert a date into a web page footer:

<html>
<body>
    <div class="top">
        <img src="banner.jpg" />
    </div>
    <div class="content">
        <h1>Content Page</h1>
        <p>Hello World</p>
    </div>
    <p>Created on <%= new Date %></p>
</body>
</html>

Dynamic Content

One of the primary reasons for views is to make it easier to create web pages with dynamic data.

Ejscript provides a set of directives to easily embed JavaScript code in your web page.

The following directives are provided:

Directive Purpose
<%= expression %> JavaScript expression
<% statements %> JavaScript statements
@@variable JavaScript variable value

<%= expression %>

Use this directive to embed the result of a JavaScript expression. The expression will be evaluated and the result converted to a string using JavaScript conversion rules.

<%= new Date().fullYear %>

<% statements %>

Use this directive to run JavaScript code statements. No value is substituted back into the page in place of the directive.

<% 
    lines = File.getLines("test.txt")
    for each (l in lines) {
        write(l)
    }
%>

The code defined via this directive is placed inside the view's render function. Any code that is valid to put in a function, is valid in this directive. NOTE: you cannot use the class keyword. A better place for such code is not in views, but in either the controller or application code.

You can also iterate over regular HTML code. The following code will display Hello World ten times in the web page.

<% for (i in 10) { %>
    Hello World
<% } %>

@@variables

Ejscript provides a shorthand for the <%= expression %> directive via the @@variable. This directive is a compact way of referencing a simple JavaScript variable.

<% today = new Date %>
<h2>Today is @@today</h2>

This directive is very useful for accessing any controller, model, application, session, request or form data.

Public variables in the controller are visible to views, as is the Model class. The application object is accessible via the app object and session data is accessible via the session object. Form data is stored in the params object.

<%
    <h2>Web Server Name: @@host.name running @@host.software</h2>
    <p>Application URL: @@app.url</p>
    table(Users.findAll())
    dump(users)
%>

See the Ejscript Library for a full list of all the properties and methods available to use in the various embedded Ejscript directives. Of particular relevance are the classes in the ejs.web namespace which include the Application, Controller, Host, Request, Response, Session and View classes.

Accessing Form Data

HTTP Form data is marshalled by Ejscript into the params object which is accessible in views and controllers. Each HTML input element posted by the client will become a property of params and can be accessed by embedded script code.

This form was generated by the view code below:

<form method="POST" action="@@request.uri">
    <p>Name: <input name="name" type="text"></p>
    <p>Address: <input name="address" type="text"></p>
    <input type="submit" name="ok" value="Ok">
</form>

This view creates three HTML form inputs and will populate the params object when posted back to the server with the properties: params.name, params.address and params.ok.

Structured Form Data

This simple mapping of input element names to params properties works fine for simple forms, but what about more complex forms? Ejscript can organize form data into nested objects. If an input element name contains a period, then Ejscript will create nested objects to match the input element name.

For example, consider the view:

<form method="POST" action="@@request.uri">
    <p>Name: <input name="user.name" type="text"></p>
    <p>Address: <input name="user.address" type="text"></p>
    <input type="submit" name="ok" value="Ok">
</form>

This will create a user object in the params object. The user object will have properties user.name and user.address. This form of structured form data makes handling form data much simpler.

Accessing Database Data

Ejscript provides an Object Relational Mapping (ORM) layer for accessing database data via convenient JavaScript objects. The ORM layer is represented by a collection of database Model classes for the application. Views can read the database by using Model classes. A more typical paradigm is for controller action routines to read a database record and store the record in a controller property. The view can then simply access the database data by referencing that property.

For more details, see Database Models.

Session Data

Data can be persistently stored between HTTP requests in the sessions object. Data stored to the sessions object is serialized, so you cannot store object references. However, the session object is ideal to store a request cookie or session key.

Themes and CSS

Well structured web applications divide HTML data and presentation style into two separate documents. Namely: HTML pages and cascading style sheets. In this way, a style sheet can be reused and shared by all pages.

It is better still to divide the style sheet into two: a layout structure style sheet and a theme style sheet. The structure style sheet specifies the order and positioning of the various sections on of the web page, whereas the theme style sheet specifies the fonts, font sizes, weights and foreground and background colors.

Ejscript supports this organization by providing a providing a directory for theme style sheet. The mvc application will also generate a default theme style sheet for scaffolds and views.

Compilation

When developing, Ejscript will automatically detect changes made to the applications code and will intelligently recompile the necessary portions of the application. You can manually force a recompilation via the mvc command.

mvc compile

See the Application Generator documentation for full details about compiling views and applications.

Debugging

You can inject debugging code into your views to trace data to the browser or to the console.

The print method will print its arguments to the console or web server log file. The dump method will serialize objects and then send to the console or log.

To send trace to the browser, use the write method to write data back to the browser. The d() method will serialize and dump objects to the browser.

View Class

The View class has a large set of utility methods to assist you in creating your web views. See the Ejscript Library for details. Some of the important methods are:

Method Name Description
anchor Emit an anchor label and reference
button Emit a form button
buttonLink Emit a button for use outside a form
button Emit a form button
chart Emit a graphic chart
checkbox Emit an input form checkbox
div Emit an HTML div
endform End an input form
flash Emit a flash message area field
form Emit a HTML form
html HTML encode the arguments
icon Emit an ICON image
image Emit an ICON image
progress Emit a progress bar
input Emit a generic input data-bound field
label Emit a text label field
list Emit a drop-down input list
radio Emit an input radio button
redirect Redirect the client to a new URL
setHeader Set a HTTP response header
setStatus Set the HTTP response status
table Render a smart table
write Write HTML data to the client
write Write data to the client

© Embedthis Software. All rights reserved.