Tutorial: "Hello World" with templates.
Now we will learn to use templates.
Requirements:
- Read Tutorial: "Hello World!" first.
- Install templates part of this project
First we would write our simple "Hello world!" template first.tmpl:
<% template main() %>
<html>
<body>
<h1><% message %> World!</h1>
</body>
<html>
<% end %>
We define a template entry main() that displays content up to <% end %>
and inserts the value of content variable message instead of <% message %>
Now we should compile it to opcode that can be read by the tmpl library.
tmpl_bld -o first.opcode first.tmpl
Then we change our "hello world program" as following:
Include tmpl library headers
#include <tmpl/content.h>
#include <tmpl/renderer.h>
using namespace tmpl;
Now we add an tmpl::renderer member to our simple class. This is the
object that will be responsible on creation of output content.
renderer rnd;
It receives
a tmpl::template_data const & as a parameter – an object that
stores a set of pre-compiled and preloaded templates. Thus our class
constructor gets another parameter:
my_hello_world(manager const &m,template_data const &t) :
worker_thread(m),
rnd(t)
{
};
Note: This can be simplified by defining a global object of template_data.
Now we change our my_hello_world::main() function as following:
void my_hello_world::main()
{
content c;
c["message"]=string("Hello");
rnd.render(c,"main",out);
}
First we define a variable c of type tmpl::content. This type is actually
derived from std::map<string,boost::any> with several extensions. This variable
will store a content that will be rendered by templates engine. Thus, we assign
a value "Hello" to content variable message in next line.
In the last line, we render final HTML code calling to template entry main
using content "c" to the output string "out". This operation fills the output
buffer with a rendered HTML code.
Now we create in main function a single instance of template_data object
that will be shared between all created worker objects.
template_data templ;
Now we can load the template from compiled opcode file using simple:
templ.load("first.opcode");
But, it is better to use configuration facilities CppCMS framework provides:
templ.load(app.config.sval("templates.file"));
After object app is created we can request the string value of variable "templates.file" that defined in our conf.txt by calling to app.config.sval(). Now we can add following line to configuration file:
templates.file = "first.opcode"
Now we need a small changes in our application main loop startup:
app.set_worker(
new one_param_factory<my_hello_world,template_data>(templ));
You can see, that now we had used another factory class one_param_factory
in order to provide an additional parameter "templ" to all created
classes. Note: this class stores a const reference to our templ object.
That’s it, now we can build and test our code:
g++ hello-tmpl.cpp -o hello-tmpl.fcgi -lcppcms -ltmpl
Tip: Definition of "cgi" api in configuration file would allow us to see an output by running simple ./hello-tmpl.fcgi -c conf.txt