<!--toc-->
|
|
## Introduction
|
|
CppCMS views are actually classes, and thus you can derive one view from other, override different templates and so on.
|
|
This gives a developer a very powerful tool to design HTML templates.
|
|
For example, we create a `master` view that includes
|
basic CSS and HTML style, and defines placeholders for different types of content that should be included. Then we derive different views that are responsible for the actual content.
|
|
master
|
/ | \
|
news page intro
|
|
|
Of course the content for the derived views should be also
|
be derived from the parent content classes.
|
|
## Content
|
|
Let's create our `content.h` for the sample hierarchy above.
|
|
First we define our `master` content in the `content` namespace.
|
|
struct master : public cppcms::base_content {
|
std::string title;
|
};
|
|
It would include shared information like our web site title.
|
|
Then we create a `news` content derived from the master:
|
|
struct news : public master {
|
std::list<std::string> news_list;
|
};
|
|
It would add some set of "news" messages we want to display.
|
|
We do the same for `page` content with, of course, different data:
|
|
struct page : public master {
|
std::string page_title, page_content;
|
};
|
|
For the "introduction" page
|
we will use the same `master` content, as we don't need more data.
|
|
## Views
|
### Master
|
|
Let's show our `master.tmpl`:
|
|
As usual we define the include and the skin name:
|
|
<% c++ #include "content.h" %>
|
<% skin myskin %>
|
|
Then we define our `master` view
|
|
<% view master uses content::master %>
|
|
We create some generic title that can be overridden.
|
|
<% template title() %><%= title %><% end %>
|
|
Define the real content we want to display
|
|
<% template page_content() %>Override Me<% end %>
|
|
And finally we define our main `render` function
|
|
<% template render() %>
|
<html>
|
<head>
|
<title><% include title() %></title>
|
</head>
|
<body>
|
<h1><% include title() %></h1>
|
<div id="content">
|
<% include page_content() %>
|
</div>
|
</body>
|
</html>
|
<% end template %>
|
|
Note:
|
|
- We use `title()` in several places
|
- We put our placeholders in the locations we want, in our
|
case it is one placeholder `page_content()`
|
|
Then we finish our `master.tmpl` as usual
|
|
<% end view %>
|
<% end skin %>
|
|
### News
|
|
Then we create our `news.tmpl`. As usual we start and end
|
it with
|
|
<% skin myskin %>
|
...
|
<% end skin %>
|
|
Then we define our view:
|
|
<% view news uses content::news extends master %>
|
|
Note:
|
|
- It `extends master` - i.e. derived from `master` view
|
- It uses `content::news` and because `content::news` derived from `content::master` it works.
|
- It uses `content::news`. It works because `content::news` derived from `content::master`.
|
|
Then we override a title using original title:
|
Then we override the title:
|
|
<% template title() %><% include master::title() %> :: News<% end %
|
<% template title() %>
|
<% include master::title() %> :: News
|
<% end %>
|
|
And define our central content:
|
|
<% template page_content() %>
|
<% foreach message in news_list %>
|
<ul>
|
<% item %>
|
<li><%= message %></li>
|
<% end %>
|
</ul>
|
<% end foreach %>
|
<% end template %>
|
|
### Page
|
|
We do the same for `page.tmpl`
|
|
<% skin myskin %>
|
<% view page uses content::page extends master %>
|
<% template title() %><% include master::title() %> :: <%= page_title %><% end %>
|
<% template page_content() %>
|
<%= page_content | raw %>
|
<% end template %>
|
<% end view %>
|
<% end skin %>
|
|
|
### Introduction
|
|
Now we create our final `intro` view, but in its case
|
we do not add any new content as we don't need it - we reuse `content::master`
|
|
<% skin myskin %>
|
<% view intro uses content::master extends master %>
|
<% template page_content() %>
|
<p><a href='<% url "/page" %>'>The Page</a></p>
|
<p><a href='<% url "/news" %>'>The News</a></p>
|
<% end template %>
|
<% end view %>
|
<% end skin %>
|
|
Note: we use `<% url ... %>` tag from the templates the same way we used it from the application in [this](wikipp/en/page/cppcms_1x_tut_url_mapping) tutorial.
|
|
|
## Controller
|
|
We create a usual mapping to `intro`, `news` and `page` functions:
|
|
dispatcher().assign("",&myapp::intro,this);
|
mapper().assign("");
|
|
dispatcher().assign("/news",&myapp::news,this);
|
mapper().assign("news","/news");
|
|
dispatcher().assign("/page",&myapp::page,this);
|
mapper().assign("page","/page");
|
|
mapper().root("/myapp");
|
|
|
Please note, because there is no direct HTML page
|
that renders `master` content we do not create a mapping
|
for it. On the other hand we do want to setup the
|
shared master content for all links.
|
So we create a small function that initializes the content:
|
|
void ini(content::master &c)
|
{
|
c.title = "My Web Site";
|
}
|
|
Then we define our "pages":
|
|
|
void intro()
|
{
|
content::master c;
|
ini(c);
|
render("intro",c);
|
}
|
void page()
|
{
|
content::page c;
|
ini(c);
|
c.page_title = "About";
|
c.page_content = "<p>A page about this web site</p>";
|
render("page",c);
|
}
|
void news()
|
{
|
content::news c;
|
ini(c);
|
c.news_list.push_back("This is the latest message!");
|
c.news_list.push_back("This is the next message.");
|
c.news_list.push_back("This is the last message!");
|
render("news",c);
|
}
|
|
|
**Notes:**
|
|
- Each one of them renders the view it needs
|
- Each one of then uses their own content
|
- Each one of them calls shared `ini()` function
|
to setup the `master` content for all.
|
|
## Building
|
|
Please note, even thought each view has its own file
|
the order of compilation is important so the `page.tmpl`
|
would be compiled after `master.tmpl`. So in our
|
Makefile we write:
|
|
cppcms_tmpl_cc master.tmpl page.tmpl news.tmpl intro.tmpl -o my_skin.cpp
|
|
It would not work of `master.tmpl` would not be the
|
first in the list.
|
|
---
|
|
← [Applications Hierarchy][prev]
|
| [Top](#maincontent)
|
| [Working With Forms][next] →
|
|
[prev]: /wikipp/en/page/cppcms_1x_tut_hierarchy
|
[next]: /wikipp/en/page/cppcms_1x_forms |