## Code |
|
Now we are going to create our first project that uses templates. |
|
CppCMS template system consists of two important parts: |
|
1. The content that is rendered to HTML |
2. The template that can render given content to HTML |
|
First we create content: |
First we create content -- `data.h`: |
|
#ifndef DATA_H |
#define DATA_H |
|
#include <cppcms/base_view.h> |
#include <string> |
|
namespace data { |
struct message : public cppcms::base_content { |
std::string message; |
}; |
} |
|
|
#endif |
|
We create a content class "message" that must be |
derived from `cppcms::base_content` class. It includes the data we want to show. In our case it is a simple string "message". |
|
It is recommended to put all "content" classes to separate namespace. |
|
Once the content is created we can create the template |
that would render out content: |
that would render out content `my_view.tmpl`: |
|
<% c++ #include "data.h" %> |
<% namespace my_view %> |
<% class message uses data::message %> |
<% template render() %> |
<html> |
<body> |
<h1><% message %> World!</h1> |
</body> |
<html> |
<% end template %> |
<% end class %> |
<% end namespace %> |
|
Every template directive enclosed by pair of `<%`, `%>`. |
|
First line `<% c++ ... %>` represents any C++ code string. We need tell our class what content should be used. Thus we give an "include" for appropriate header. |
|
Then we define namespace where all our templates are placed `<% namespace my_view %>` and then create a class that renders our content. |
|
<% class message uses data::message %> |
|
Class my\_view::message would render data::message content. The primary function that should be implemented is "render()". After `<% template render() %>` we write the |
body of our html message. |
|
You can see `<% message %>` command. It tells that "message" member of our content class should be displayed. |
|
**Note:** Every std::string automatically receives HTML escaping. Thus it is safe to show any row data there. |
|
Now, lets see how we use it in our code. |
|
First we call `use_template("my_view")` in the constructor of `my_hello_world`. It tells to application, which template set should be used for rendering. |
|
Then, in `main()` function we write: |
|
data::message c; |
c.message=">>>Hello<<<"; |
render("message",c); |
|
We create an instance of `data::message` --- "c". We set its `message` member with appropriate string we want to show. We may safely put any symbols like "<", they would be |
automatically escaped. |
|
Then we call `render("message",c)`. It would use `my_view::message` class for rendering template content "c". |
|
That's it. |
That's it, the code is complete. |
|
## Build |
|
There are two options of building templates: |
|
1. Statically compile them into the executable |
2. Compile them as shared object and load them with application start-up. |
|
### Static build |
|
First we compile our template |
|
cppcms_tmpl_cc my_view.tmpl -o my_view.cpp |
|
Then we can build our project |
|
g++ hello.cpp my_view.cpp -lcppcms -o hello.fcgi |
|
Now we run as usuall `cppcms_run hello.fcgi -c conf.txt` |
|
### Dynamic build is little bit more tricy. |
|
After we had build our `my_view.cpp` we should compile it |
as shared object: |
|
g++ -shared -fPIC my_view.cpp -lcppcms -o my_view.so |
|
Then compile our application with additional flag `-export-dynamic`. |
|
g++ -export-dynamic hello.cpp -lcppcms -o hello.fcgi |
|
Without this flag, RTTI, would not work between application |
and shared object and you may receive a error "incorrect content type". |
|
Now we should let our application know where its templates |
are placed. We edit conf.txt and add following line: |
|
templates.dirs={ "." } |
|
When `hello.fcgi` starts, it would look in this directory |
and try load all shared object it finds. |
|
Now we can start our application as usual. |