[[#wd Lookup TitleRecipe25 ]]

Overview

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:

  1. Retrieval of the data that needs to be visualized, and transformation of that data into an Anything representation: The concrete structure of the Anything depends on the Renderer to be used for creating the final output (e.g. HTML). It may be tailored to the needs of an existing Renderer. Alternatively a new Renderer may be created to handle any specialized Anything data structure.
  2. The Anything is then used as input for the rendering process by placing it - under a well known slot name - in the Context before any rendering is started.
  3. The concrete Renderer to utilize the data needs to be configured properly - so as to find the data - and may then be used as a building block for the Page that wants to dynamically create some content.

(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.)

Preconditions

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)"
		"..."
	}
}]]

Steps to do:

  1. A string containing the current date is easily created by the following C++ code:
    [[#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.)

  2. The Anything created in step 1 is now typically placed in the AppTmpStore for later processing by the Renderers. In this example the data is put at slot 'currentDate'.
    (Eventhough the data may - in principle - be placed anywhere in the Context, AppTmpStore is the right choice when it comes to data that is used for one particular request only. An empty AppTmpStore is used for each new request and it is discarded after the request is processed, i.e. it acts as a scratch pad.)

    The question that needs to be answered now is were exactly to place the C++ code shown above. There are two alternatives:

    Whether we create code for the Action::DoAction() or the Page::Preprocess() the AppTmpStore is modified before any rendering takes place!

  3. Whenever page Ex4Page is now reached (in the first case via GoExample4) we can safely assume that slot 'currentDate' in AppTmpStore contains a string with the current date. We may therefore use a simple ContextLookupRenderer to lookup and display that string:
    Ex4Page.html:
    [[#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:
    Ex4Page.any:
    [[#wd DisplayAnythingRenderer {
    	/AnythingInfo {
    		"..."
    		"/ArbitraryRendererSpec {"
    		"	/Lookup {"
    		"		/ContextLookupName	"currentDate""
    		"	}"
    		"}"
    		"..."
    	}
    }]]
    
    Ex4Page.html:
    [[#wd DisplayAnythingRenderer {
    	/AnythingInfo {
    		"...."
    		"[[#wd Lookup ArbitraryRendererSpec ]]"
    		"..."
    	}
    }]]
    

Remarks

Glossary

Related Topics

ContextLookupRenderer, Page configuration