-
Notifications
You must be signed in to change notification settings - Fork 0
3.8.1 Template Expressions
Template expressions in layouts (views/layouts/*.ehtml
) provide methods for generating HTML
that link layouts to external JavaScript and stylesheet files.
You can use these tags in layouts and even in views, although these tags are most
commonly used in the <header>
section of a layout. Note that the asset tag helpers
do not verify the existence of the assets at the specified locations; they simply assume
that you know what you are doing and generate the link.
The @script
expression returns an HTML script
tag for the specified location.
For example, to link to a JavaScript file datebox.js
that is the directory content/libs/
inside of the /assets/www/
folder:
@script("content/libs/datebox")
The generated script tag would be:
<script type="text/javascript" src="content/libs/datebox.js">
</script>
The stylesheet_link_tag
helper returns an HTML link
tag for each source provided.
This helper generates a ling to /assets/www/content/stylesheets/
. For example,
to link to a stylesheet file main.css
in the sub-directory ui_style/
located at
the /assets/www/content/stylesheets/
folder, you would do this:
@style("uistyle/main")
MMIR will then generate the following link tag:
<link rel="stylesheet" href="content/stylesheets/uistyle/main.css"/>
Within the context of a layout, @yield
identifies a section where content from
the view should be inserted. The simplest way to use this is to have a single @yield
,
into which the entire contents of the view currently being rendered will be inserted:
<html>
<head>
</head>
<body>
@yield("yield-name")
</body>
</html>
You can also create a layout with multiple yielding regions:
<html>
<head>
@yield("head")
</head>
<body>
@yield("content")
</body>
</html>
The main body of the view will always render into the unnamed yield.
To render contents into the @yield
section, you should use
the @contentFor
expression in the view definitions.
Template expressions in views (views/<controller name>/*.ehtml
) are used to specify the the contents
of @yield
sections that were declared in layouts.
In addition, several expressions allow defining dynamic content (i.e. content that is produced / modified
at the time, when the view will be displayed), including control expressions like @if
and @for
.
The @contentFor
expression is used to specify the contents
that are rendered into the corresponding yield
section of a layout definition.
For example, the following view definition would specify contents for yield
sections with the names head
and content
(cf. the example above):
@contentFor("head"){
<title>A simple page</title>
}@
@contentFor("content"){
<p>Hello, MMIG! </p>
}@
The result of rendering this page into the supplied layout would be this HTML:
<html>
<head>
<title>A simple page</title>
</head>
<body>
<p>Hello, MMIG! </p>
</body>
</html>
Using multiple @contentFor
expressions (in combination with the corresponding
@yield
sections) can help modularizing a page into distinct regions.
The order in which the contentFor blocks are specified does not matter: in the example above you could also specify the contentFor "content" before the "head" – the result would be the same.
The framework allows an easy way of localization. It uses a dictionary to lookup the corresponding localized text for a supplied key:
<label for="login">
@localize("login_label")
</label>
Note that the language must be set and a dictionary (file) must exist, before the localization can be used properly.
On rendering, the localize
expression is replaced by the corresponding value for the currently set language.
In context of the StaterKit example, when the setting en
as language, then example dictionary for English would be used,
(cf. section Add a new Dictionary)
and the result would be:
<label for="login">
Login
</label>
Comments are enclosed by @*
and *@
.
Comments will not be displayed in the rendered view in any way.
All content that is within a comment section is not processed by the
parser and will be removed before the view is rendered.
A little example the comments statement in action:
<html>
<head>
@* Here comes the title of the view *@
<title>A simple page</title>
</head>
<body>
@* and here is the body contents *@
<p>Hello, MMIG! </p>
</body>
</html>
This will result in:
<html>
<head>
<title>A simple page</title>
</head>
<body>
<p>Hello, MMIG! </p>
</body>
</html>
The contents of the comments statements is simply removed.
The comments expression can also be used for (temporarily) disabling template expressions:
...
<div>Upcoming events:
@* not implemented yet: @render('Calendar', 'my_time_table') *@
@( MY_DUMMY_DATA.timeTableStub )
<div>
...
Dynamic template expressions are evaluated immediately before the view will be displayed.
Template variables can either be displayed in the view
(cf. section Rendered javascript)
or manipulated inside a JavaScript code segment – see following sections.
The access to the variable is limited to the surrounding contentFor block of the view
(see section Using @contentFor
).
If the variable is used within a partial, it is accessable throughout the whole partial as a partial is an implicit contentFor section.
@var(title_string)
@{@title_string = "Title String"}
<html>
<head>
<title>@(@title_string)</title>
</head>
<body>
<p>>@(@title_string)</p>
</body>
</html>
The use of @var
and the @
prefix makes the variable's scope local for this template. This also means that no global variable with the same name is overwritten or the value from a global variable is used instead of a local created variable.
The variable will only be replaced by its value on rendering, if it is used inside a (rendered) javascript section –
see section Rendered javascript code @( ... )).
Simply adding @variable
to a view will just result in rendering @variable
at this position – instead of the value of var
.
If a variable is used inside a javascript code block (unrendered or rendered), it should be initiated with
@var()
and referenced with@
to ensure that the variable is not overwriting a global variable.Note that variables are not permitted inside a layout description.
This expression evaluates the containing javascript code but does not render the return value. Inside the code block standard javascript can be used. See also the section about variables for a brief explanation about the scope of variables.
The following snippet is an example of how to use the unrendered javascript code:
@{@page_name = "simple page";}@
@{
@dots="";
for (@i = 0; @i < 30; @i = @i + 1){
@dots = @dots + ".";
}
}@
<html>
<head>
<title>A simple page</title>
</head>
<body>
<p>Hello, MMIG! </p>
</body>
</html>
The first line simply assigns a value to the variable page_name
.
The section beginning on the second line creates a string with 30 dots.
All these commands are simply executed, but nothing is rendered for it in
the final view. So the rendered, it will just look like this:
<html>
<head>
<title>A simple page</title>
</head>
<body>
<p>Hello, MMIG! </p>
</body>
</html>
Note that the un-rendered javascript code block can contain multiple lines of code.
This expression evaluates the containing javascript code and displays the return value into the location of the template expression. Inside the code block standard javascript can be used. See also the section about variables for a brief explanation about the scope of variables.
This example shows the usage of a rendered javascript code:
@{@page_name = "simple page";}
<html>
<head>
<title>A simple page with the name @(@page_name)</title>
</head>
<body>
<p>Hello, MMIG! </p>
</body>
</html>
The variable page_name
is replaced with the string assigned to it, resulting in the following code:
<html>
<head>
<title>A simple page with the name simple page</title>
</head>
<body>
<p>Hello, MMIG! </p>
</body>
</html>
As seen above, this construct is used to display template variable values.
Note that the rendered javascript code block cannot contain multiple lines of code – it is mainly used for the display of template variables. In contrast, the unrendered javascript code can contain multiple lines of code.
If a helper method is defined for a controller, it can be called from within a view. The helper's return value is then rendered into the view at the position of the helper call.
The syntax of the helper call is:
@helper(functionName : String [ , data : <String|Number|Boolean|PlainObject> ])
The first argument functionName
is the name of the helper function.
The controller need not to be specified:
the helper expression always refers to current view's controller.
The helper function can be called with an optional data
argument.
When the view is rendered, the helper method is invoked and its return value will replace the template expression in the rendered view.
If a
data
argument is passed to a helper function via thehelper
call, this data can be accessed inside the helper function by using thearguments
variable. Thearguments
variable holds data-argument of the helper call at the 3rd position:
function the_helper_function(ctrl, viewData, data)
(for more detials see section Accessing data arguments)
This snippet calls a helper method named createListElements
with
{obj1 : 'value1', obj2 : 'value2'}
as data argument and renders the return value in place of the helper expression:
<html>
<head>
<title>A simple page</title>
</head>
<body>
<p>Hello, MMIG! </p>
@helper('createListElements',
{obj1 : 'value1', obj2 : 'value2'})
</body>
</html>
Using a partial expression @render
in a view, will evaluate the partial's definition and
render its result in place of the @render
statement.
The syntax for the @render
statement is:
@render(controllerName : String, partialName : String [ , data : <String|Number|Boolean|PlainObject> ])
The controllerName
is the name of the controller which is associated with the partial,
and partialName
is the name of the partial.
Note that partial definitions from any view can used; the @render
statement is not restricted to
the current view's controller.
This allows to specify re-usable "template-snippets" across controllers.
The data
argument allows for the passing of arguments to the partial, e.g. ascertained by a helper method. The type of the data argument can be one of the following: a string / number literal, template variable or a JSON like object, which itself can consist of an array, string / number literal and a JSON like object.
If a data argument is passed to a partial via the
render
call, the data can be referenced inside the called partial by using the@argument
variable. This variable holds the arguments of the render call.
For example, the following render expression would render the partial definition
in file ~languageMenu.ehtml
of the Application
controller. The (optional)
data
argument can be accessed from within the partial defintion via the @argument
expression.
<html>
<head>
<title>A simple page</title>
</head>
<body>
<p>Hello, MMIG! </p>
@render('Application', 'languageMenu',
{displayTitle : true, salutation : "Bob"})
</body>
</html>
Inside the partial definition for languageMenu
, the data argument {displayTitle : true, salutation : "Bob"}
can be referenced via the @argument
variable
(cf. Accessing data arguments).
Template control expressions let you manipulate the control flow for rendering a view: they control / modify if and how a view will be rendered.
TBD: add details and examples for template expressions (see example for partial in /views/application/~languageMenu.ehtml).
For the control of the rendered view output, the @if
construction can be used to display parts of the code only if a defined condition is true.
The syntax is:
@if (javascript condition) {
part to display if condition is true – view expressions or HTML
}@ [ @else{
part to display if condition is false – view expressions or HTML
}@ ]
The else-part is optional. Inside the if segments all view expressions, including HTML, can be used.
An example of a conditional rendering:
@{@debug = true;}
<html>
<head>
@if(@debug == true){
<title>Debug mode</title>
@{@debug_time = new Date();}
}@ @else {
<title>A simple page</title>
}@
</head>
<body>
<p>Hello, MMIG! </p>
@if(@debug == true){
<div id="debug_info"></div>
}@
</body>
</html>
This would result in the rendered view:
<html>
<head>
<title>Debug mode</title>
</head>
<body>
<p>Hello, MMIG! </p>
<div id="debug_info"></div>
</body>
</html>
The if statement can be used hierarchically – just like in javascript.
For the generation of similar view sections, e.g. menu items, the @for
statement can be used.
The @for
statement has two versions:
- using counter variable
- or for iterating over an object's properties
The syntax is:
@for (initialization; condition; incrementStatement) {
loop body
}@
or:
@for (propertyName in object) {
loop body
}@
The following snippet creates a list of the work days of the week by using a counter:
<html>
<head>
<title>A simple page</title>
</head>
<body>
<p>Hello, MMIG! </p>
@{ @daysArray = ["mon", "tue", "wed", "thu", "fri"]; }@
<ul>
@for(@i=0, @size = @daysArray.length; @i < @size; ++ @i){
<li>@(@daysArray[@i])</li>
}@
</ul>
</body>
</html>
The results is:
<html>
<head>
<title>A simple page</title>
</head>
<body>
<p>Hello, MMIG! </p>
<ul>
<li>mon</li>
<li>tue</li>
<li>wed</li>
<li>thu</li>
<li>fri</li>
</ul>
</body>
</html>
Alternatively, the same can be achieved by using the iterative version of the @for
statement as follows:
<html>
<head>
<title>A simple page</title>
</head>
<body>
<p>Hello, MMIG! </p>
@{ @daysArray = ["mon", "tue", "wed", "thu", "fri"]; }@
<ul>
@for(@i in @daysArray){
<li>@(@daysArray[@i])</li>
}@
</ul>
</body>
</html>
If the at sign, @
itself has to be displayed in a view,
it must be "escaped" by second @
:
@@
will be rendered to @
.
For example, in a template file:
@if( @data.email ){
<div>e-mail: some@@mail-address.com</div>
}@
will be rendered as
<div>e-mail: some@mail-address.com</div>
(that is, if the templae's @if
expression is evaluated to true
)
The expressions for helper functions, as well as the expression for rendering
partials, allow to for a data
argument:
@helper('function_name_within_the_helper', data)
and
@render('controller_name','partial_name', data)
This data
arguement can be accessed in the helper function - or partial definition -
through the arguments
variable (helper function), or using the
@argument
expression (within the partial's template definition) respectively.
For example, within a partial definition, data argument {some: 'data'}
can be accessed via the @argument
variable:
<div>
The supplied arguments are: @(JSON.stringify(@argument.some))
</div>
As for accessing the data
argument from the helper function implementation:
here, the signature for a helper function actually takes three arguments:
-
the controller name
controller
of the helper (ctrl
) -
the
data
argument, that is used for rendering the view (viewData
)
this is thedata
-argument from the context where the helper expression itself is used, i.e. the optionaldata
-argument for therender
-function of thePresentationManager
, e.g.mmir.dialog.render('Application', 'login', viewData)
-
the
data
argument used in the helper expression (callData
)
this is thedata
-argument that is specfied in the helper expresson, e.g.@helper('function_name_within_the_helper', callData)
So for example, within the helper function, the data argument {some: 'data'}
from the
helper expression can be accessed via the 3rd position in the arguments
variable:
function function_name_within_the_helper(ctrl, viewData, callData){
//accessing the call-data by name
// (as specified in the function's definition)
if(callData.some === 'data'){
// do something
}
//... or generically via arguments:
if(arguments[2].some === 'data'){
// do something
}
}
If a call to render a view is also supplied with arguments, these can be accessed with the @data
template variable. Calls to render views are typically generated by the state machine and can be supplied with additional parameters to create contextual rendered output.
A call to render the loginManager
view may look like this:
mmir.dialog.render(
'Application', 'login', {languageMenu : true}
);
Inside the view login
, the property languageMenu
can be accessed by referencing to @data.languageMenu
,
which will yield true
.
< previous: "Application Views" | next: "Setup MMIR for Internationalization" >
- 1 Introduction
- 2 What is MMIR
- 3 MMIR Project Structure
- 4 Getting started