Main  /  Edit version 10  /  Edit version 11  /   /  Users Area

Difference "Templates: Flow Control (v 1.x)" ver. 10 versus ver. 11

Content:

<!--toc-->
## Conditions
### Syntax
Begin or continue conditional statement:
( 'if' | 'elif' ) [ 'not' ] [ 'empty' ] ( VARIABLE | 'rtl' )
( 'if' | 'elif' ) '(' any-c++-expression ')'
Else block:
'else'
Each if/else block should be ended with `end` statement. For example:
<% if not empty username %>
<h1>Hello <% username %></h1>
<% else %>
<h1>Hello Visitor</h1>
<% end %>
<% if ( content.n % 2==0 ) %>
<% n %> is odd.
<% elif ( content.n % 3 ==0) % >
<% n %> can be divided by 3 without reminder.
<% end %>
### Description
This is ordinary `if`/`else if` statement. You can specify following conditions:
- By specifying variable or property you check whether it is true.
- By specifying `empty` keyword you may check if specific STL container is empty by calling its member `empty()`.
- You can negate the result using `not`
- You can also check whether current locale referred to Right-To-Left language like Hebrew, Arabic or Persian by specifying `rtl` keyword.
This condition actually checks in dictionary if string "LTR" is translated as "RTL".
- You can specify arbitrary C++ conditional expression withing round brackets `()`. _Note_: Do not forget to refer to content variables using `content.` prefix.
## Foreach block
### Sytnax
Major loop:
'foreach' NAME ['as' IDENTIFIER ] [ 'rowid' IDENTIFIER [ 'from' NUMBER ] ] [ 'reverse' ] 'in' VARIABLE
In case of empty collection:
'empty'
Specify central body:
'item'
'separator'
For example:
<% foreach student in students %>
<ul>
<% item %>
<li><% student.id %>, <% student.name %></li>
<% end %>
</ul>
<% empty %>
<h2>No students</h2>
<% end %>
You can specify delimiter for elements between `separator` and `item` block:
<% foreach student in students %>
<% separator %>, <% item %><% student.name %><% end %>
<% end %>
Would generate a list like: "Ron, John, Moshe"
### Description
`foreach` loop creates a for loop that iterates any STL collection. The given name is a reference to
the type returned by iterator. For example, if students is `std::list<student_t>` then `student` in above
example is defined as `student_t &student`.
- `reverse` - orders to use reverse iterator (rbegin,rend)
- `rowid` - defines a special integer index that
can be used for enumerating rows and optional `from` defines initial index value (default 0)
For example
<% foreach line rowid from 1 num in code %>
<% foreach line rowid num from 1 in code %>
<% item %><%= num %>:<%=line%><% end %>
<% end %>
_Note:_ `reverse` and `rowid` are supported starting from CppCMS 0.99.10
#### Type detection
Template system uses one of following method for automatic type detection:
1. C++0x `auto`
2. C++0x `decltype`
3. GCC's style `typeof` or `__typeof__`
At least one of them should be supported by the compiler in order to provide correct template generation without
using `as` keyword.
But some compilers, most noticeable is MSVC8, MSVC9 still
not support automatic type detection, thus, specific
iterator type should be explicitly specified.
For example:
<% foreach student as students_type::iterator in students %>
Would give you correct solution for MSVC compiler and `student` would a variable of type `students_type::iterator::value_type`
#### Body
`empty` statement is equivalent to "else" so:
<% foreach a in b %>
<ul>
<% item %><% a %><% end %>
</ul>
<% empty %>
nothing
<% end %>
Is generated into code like:
if(!content.b.empty()) {
out()<<"<ul>";
for(auto a_it=content.b.begin();a_it!=content.b.end();++a_it) {
auto &a=*a_it;
out()<<a;
}
out()<<"</ul>";
}else{
out()<<"nothing";
}
You must provide `<% item %>...<% end %>` block for any `foreach` statement.
If `separator` is used it should be added between `separator` and `item` blocks.
### Custom form rendering
CppCMS forms system provides several options for rendering form widgets, but sometimes custom rendering
may be needed. In this case, `foreach` can be used to iterate over `cppcms::form` as over ordinary collation.
For example, rendering with "new line" separator:
<% foreach w in form %>
<% separator %><br/><% item %>
<% if w.has_message() %><% w.message() %>:<% end %>
<% form input w %>
<% if not w.valid() %>:<% w.error_message() %><% end %>
<% end %>
<% end %>
## Caching Elements
### Syntax
The cached block begins with cache statement
'cache' ( VARIABLE | STRING ) [ 'for' NUMBER ] ['on' 'miss' VARIABLE() ] [ 'no' 'triggers' ] [ 'no' 'recording' ]
and ends with `end` statement.
For example
<% cache "sidebar" for 10 %>
...
<% end cache %>
### Description
This block allows to cache parts of rendered
templates. The first parameter `( VARIABLE | STRING )`
is mandatory and defines the key that is used to
retrieve the frame from the cache. It should be
either constant predefined string or some variable
stored in the context.
- `for NUMBER` - defines the number of seconds this block
is stored.
- `on miss VARIABLE()` defines the callback function that should be called if cache miss occurs. It allows for example
to populate the context with some more data from the
database.
- `no triggers` - says that the cache key should not be added as trigger to the general cache. By default the key is added to the current triggers set, if `no triggers` defined it does not happen.
For example:
<% cache "foo" %>
<% cache "bar" %>
<% end %>
<% end %>
The `bar` trigger is added to `foo` and to all higher
level object as dependent trigger. Thus calling
`rise("bar")` would invalidate "foo" frame.
However if you write:
<% cache "foo" %>
<% cache "bar" no triggers %>
<% end %>
<% end %>
Then rising "bar" would not invalidate "foo".
- `no recording` prevents from this object to record
all triggers that where added during frame generation.
For example:
<% cache "foo" on miss load_data() %>
...
<% end %>
void load_data(some_content &c)
{
c.foo = .. // load some data from S
cache().add_trigger("my_data");
}
If `load_data()` is called it would add a trigger
"my_data" to the cache and thus rising `my_data`
would invalidate "foo".
If `no recording` is provided
<% cache "foo" on miss load_data() no recording %>
Then the rising `my_data` would not invalidate
"foo".
## Adding Cache Triggers
Strictly speaking this is not flow block but it
is strongly connected to the `cache` block described
above.
trigger ( STRING | VARIABLE )
Says to add trigger to the current context effectively
calling `cache().add_trigger(value)`
For example:
<% cache "foo" %>
...
<% trigger "bar" %>
<% end cache %>
Now rising `bar` as trigger would invalidate `foo` object.
It is useful for some complex relations where you want
to add triggers to cached frames explicitly.

About

CppCMS is a web development framework for performance demanding applications.

Support This Project

SourceForge.net Logo

Поддержать проект

CppCMS needs You


Navigation

Main Page


Valid CSS | Valid XHTML 1.0