There are many applications where the content of a page cannot be statically defined but - since it depends on some mutable data - has to be determined at runtime (By querying a database, reading a file, using some proprietary middleware, etc. Examples might be current stock quotes, customer data like account statements, personal profiles etc.)
This recipe explains what needs to be done to use dynamic data for the rendition of some page content.
There are basically three steps to be taken:
(Caution: Once the data is in the Context, in principle any Renderer - that wishes to do so - may use it to create some output. This implies that it is the responsibility of the application to avoid possible conflicts - e.g. corruption of data that is used by multiple Renderers.)
In the following example the page Ex4Page (which is a sub-page of Page) is to
display some dynamic output, i.e. the current date. Initially Ex4Page simply
displays the static HTML template Ex4Page.html. The action that leads to
Ex4Page is GoExample4. It is assumed that all the respective configuration data is
setup properly - i.e. no C++ code was yet written but the configuration files
contain something like this:
Config.any:
[[#wd DisplayAnythingRenderer { /AnythingInfo { "/Roles {" " /Role {" " "Default"" " }" "}" " " "/Pages {" " # subclasses for "Page"" " "Ex4Page"" " ..." "}" " " } }]]
Role.any:
[[#wd DisplayAnythingRenderer { /AnythingInfo { "/Map {" " /Default {" " /GoExample4 "Ex4Page"" " ..." " }" "}" " " } }]]
Ex4Page.any:
[[#wd DisplayAnythingRenderer { /AnythingInfo { "/PageLayout {" " /HTML {" " /TemplateName "Ex4Page"" " }" "}" " " } }]]
Ex4Page.html:
[[#wd DisplayAnythingRenderer { /AnythingInfo { "...." "(the current time should go here)" "..." } }]]
[[#wd DisplayAnythingRenderer { /AnythingInfo { "time_t now;" "time(&now);" "struct tm res;" "struct tm *tt= localtime_r(&now, &res);" " " "char date[200];" "strftime(date, 100, "%C", tt);" } }]]Putting the date into an Anything is straight forward too:
[[#wd DisplayAnythingRenderer { /AnythingInfo { "Anything anyDate= Anything(date);" } }]](The example is deliberately kept very simple. However a real application might retrieve some arbitrary data at this point - e.g. using a database.)
The question that needs to be answered now is were exactly to place the C++ code shown above. There are two alternatives:
[[#wd DisplayAnythingRenderer { /AnythingInfo { "class GoExample4 : public Action {" "public:" " GoExample4() {}" " bool DoAction(String &action, Context &c);" "};" " " "RegisterAction(GoExample4);" " " "bool GoExample4::DoAction(String &action, Context &c)" "{" " Anything tmpStore= c.GetTmpStore();" " " " time_t now;" " time(&now);" " struct tm res;" " struct tm *tt= localtime_r(&now, &res);" " " " char date[200];" " strftime(date, 100, "%C", tt);" " " " tmpStore["currentDate"]= date;" " " " return true;" "}" } }]]
[[#wd DisplayAnythingRenderer { /AnythingInfo { "class Ex4Page : public Page {" "public:" " Ex4Page();" " Ex4Page(const char *title);" " " " virtual void Preprocess(Context &c);" " IFAObject *Clone() const;" "};" " " "RegisterPage(Ex4Page);" "Ex4Page::Ex4Page() : Page("Ex4Page") {}" " " "IFAObject *Ex4Page::Clone() const" "{" " return new Ex4Page;" "}" " " "void Ex4Page::Preprocess(Context &c)" "{" " Anything tmpStore= c.GetTmpStore();" " " " time_t now;" " time(&now);" " struct tm res;" " struct tm *tt= localtime_r(&now, &res);" " " " char date[200];" " strftime(date, 100, "%C", tt);" " " " tmpStore["currentDate"]= date;" "}" } }]]
[[#wd DisplayAnythingRenderer { /AnythingInfo { "..." "[[#wd Lookup currentDate ]]" "..." } }]]More complex Renderers may require more configuration data than just a single slot-name like 'currentDate'. The Renderer specification is then conveniantly put in the configuration file of the page and is rendered indirectly into the HTML template:
[[#wd DisplayAnythingRenderer { /AnythingInfo { "..." "/ArbitraryRendererSpec {" " /Lookup {" " /ContextLookupName "currentDate"" " }" "}" "..." } }]]Ex4Page.html:
[[#wd DisplayAnythingRenderer { /AnythingInfo { "...." "[[#wd Lookup ArbitraryRendererSpec ]]" "..." } }]]
ContextLookupRenderer, Page configuration