Main  /  Edit  /  History  /   /  Users Area

Tutorial: Using Templates (v 1.x)

Introduction

CppCMS is an MVC web framework. One of its important parts is view - the HTML rendering system.

CppCMS's web pages are written in a special template language, that is translated to C++ code that can be compiled to a shared object (or DLL on windows) or be statically linked into your applications.

Generally the CppCMS template system uses a push model, where the user application prepares the content and pushes it to the web template system for rendering.

For proper rendering of templates two stages are required:

  1. Your application (controller) prepares the "content" for the HTML template system.
  2. The content returned to the users is rendered to HTML using the template system.

Code

In order to work with templates we need to separate our source into three parts:

The content

The content declarations will appear in the "content.h" file:

#include <cppcms/view.h>
#include <string>

We need to include the header <cppcms/view.h> that will provide us with all the definitions required as a base for our content class.

namespace content  {
    struct message : public cppcms::base_content {
        std::string text;
    };
}

Each content object should be derived from the class cppcms::base_content and should store all relevant data.

So we've created a small structure 'message' that holds a single string text that will be rendered with an HTML template.

As a rule of thumb we put all our content objects in a separate namespace.

The template

All web templates are separated into skins - the specific implementation of the view that can vary for the same content. Each skin is placed in the namespace with the same name.

Each skin consists of a set of views - the representation of a single page. All views can be organized into a hierarchy of views. Each view can extend the base view with more features and redefine its templates. The views are represented with classes, each one of them being responsible for rendering a specific content object.

As a rule of thumb we name them the same way as the corresponding content classes.

Each view consists of a set of templates. The base template, which is always rendered, is called render. render should always be implemented.

So lets see out first template:

<% c++ #include "content.h" %>
<% skin my_skin %>
<% view message uses content::message %>
<% template render() %>
<html>
  <body>
    <h1><%= text %> World!</h1>
  </body>
</html>
<% end template %>
<% end view %>
<% end skin %>

In the first line we use C++ inline code to include the appropriate header.

Then we define our skin called simply "my_skin" and then in line 3 we define our view. We call it "message", the same as our content's class. We declare that is would render an object of type 'content::message'.

Then in line 4 we define the function that actually renders all the HTML for us - render.

On line 7 we display a member text of the content::message in the HTML. Note: the displayed text will be automatically escaped with HTML entities, for example < will be converted into &lt;.

The controller

Similarly to our "hello world" example we define the main function of our application. Before this, we have included our content.h header.

Our headers:

#include <cppcms/application.h>
#include <cppcms/applications_pool.h>
#include <cppcms/service.h>
#include <cppcms/http_response.h>
#include <cppcms/url_dispatcher.h>
#include <iostream>

#include "content.h"

Our main class:

class my_hello_world : public cppcms::application {
public:
    my_hello_world(cppcms::service &s) :
    cppcms::application(s)
    {
    }
    virtual void main(std::string /*url*/)
    {
        content::message c;
        c.text=">>>Hello<<<";
        render("message",c);
    }
};

Our main function:

int main(int argc,char ** argv)
{
    try {
        cppcms::service srv(argc,argv);
        srv.applications_pool().mount(cppcms::applications_factory<my_hello_world>());
        srv.run();
    }
    catch(std::exception const &e) {
        std::cerr<<e.what()<<std::endl;
    }
}

We create an object c of type content::message and set the value for its text member with an arbitrary HTML unsafe string.

Then we call the render member function of cppcms::application with the following parameters:

  1. The name of the view for the default skin. It generally matches the name of the content class, in our case "message".
  2. The content object itself that holds all of the data that the HTML template needs.

After calling it, the HTML will automatically be written to the output.

Building Templates

The template shown above should be compiled into C++ code in order to be useful. We do this with a special compiler, as follows:

cppcms_tmpl_cc my_skin.tmpl -o my_skin.cpp 

The created my_skin.cpp contains all the code needed for rendering and registering this skin in CppCMS's rendering system.

Linking Statically

Now, my_skin.cpp should be compiled and linked together with your application:

g++ hello.cpp my_skin.cpp -o hello -lcppcms -lbooster

And we can run our application as usual:

./hello -c config.js

Dynamic loading

Dynamic linking is a little bit more tricky, but it is much more powerful as it allows you to load skins without relinking the application. You can even update your application without needing to restart it.

First we create a shared object from our my_skin.cpp file, and name it with the same name as our skin:

g++ -shared -fPIC my_skin.cpp -o libmy_skin.so -lcppcms -lbooster

(Or for GCC 4.7 on OSX, we create it like this:)

g++ -shared -fPIC my_skin.cpp -o libmy_skin.dylib -lcppcms -lbooster

Now we compile our hello application without my_skin.cpp but we pass an additional parameter -rdynamic in order to allow shared library to see symbols in the application:

g++ -rdynamic hello.cpp -o hello -lcppcms -lbooster

(Or for GCC 4.7 on OSX, we compile it like this:)

g++ -dynamic hello.cpp -o hello -lcppcms -lbooster

Now our system is almost ready to run, we just need to add into our configuration description which skins should be loaded dynamically. We add the following section to config.js:

"views" : {
    "paths" : [ "." ],
    "skins" : [ "my_skin" ]
}

Now run the application as usual and it will load the skins and use them.


Hello World (v 1.x) | Top | URL Dispatching and Mapping

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