Grantlee
5.1.0
|
As already noted, it is possible for application developers to create their own tags and filters. This feature is based on the QtPlugin system so that plugins can be loaded at run time.
A filter takes an object and an optional argument and returns a string. To create your own filter, create a concrete subclass of Grantlee::Filter and implement the doFilter method.
The argument to doFilter is a QVariant, so it may contain any of the types supported by Grantlee.
Note that the filter does not fail or throw an exception if the integer conversion fails. Filters should handle all errors gracefully. If an error occurs, return either the input, or an empty string. Whichever is more appropriate.
When implementing filters, it is necessary to consider whether string output from the template should be escaped by Grantlee when rendering the template. Grantlee features an autoescaping feature which ensures that a string which should only be escaped once is not escaped two or more times.
The filter interface contains two elements relevant to autoescaping. The first is the autoescape parameter to the Filter::doFilter method. The autoescape parameter indicates the current autoescaping state of the renderer, which can be manipulated in templates with the {% autoescape %}
tag. Use of the autoescape parameter is rare. The second element of autoescaping in the Filter API is the Filter::isSafe method. This method can be reimplemented to indicate that a Filter is 'safe', that is given safe input, it produces safe output.
A tag can really do anything with a template. To create your own tag, create a concrete subclass of Grantlee::NodeFactory and implement the getNode method, and create a concrete subclass of Grantlee::Node and implement the render method.
Tags can take arguments, advance the parser, create nodes, and generally have broad control over the parsing and rendering stages.
Here is an example of a {% current_time %}
tag which displays the current time.
{% now %}
tag. See its documentation and implementation for details.Also, note that, nodeFactory may throw an execption at template compilation time, but like Filters, Nodes should handle errors gracefully in their render method, and should return an empty QString in most error cases.
Often, tags will be not just one token in a template, but a start and end token such as range, spaceless, with, or a start, middle and end tokens, such as if and for.
When constructing a Node, a NodeFactory can instruct the Parser to parse until any appropriate Token.
To implement such a tag the implementation of AbstractNodeFactory::getNode needs to parse until the optional intermediate tags and until the mandatory end tag, collecting the child nodes as it does so.
There is no limit to the number of intermediate tokens you can use in your tags. For example, a better {% if %}
tag might support multiple elif tags.
As already mentioned, it is neccessary to create a QtPlugin library to make your tags and filters available to Grantlee. You need to implement TagLibraryInterface to return your custom node factories and filters. See the existing libraries in your Grantlee distribution for full examples.
If you configure your application to use the grantlee_scriptabletags_library, it will be possible for you and theme writers to write tags and filters in QtScript instead of C++. Themers would have as much control as a C++ plugin writer over those steps of processing and rendering the template.
Writing QtScript plugins is slightly different from writing C++ plugins, and is a bit more like writing Django plugins. Namely, in Javascript like python, functions are first-class objects, and javascript is dynamically typed. Additionally QtScript plugins are just text files, so they can easily be dynamically loaded at runtime. QtScript files must be UTF-8 encoded.
Here is a complete QtScript library defining an {% echo %}
tag which outputs its arguments:
Some things to note:
As noted in Creating Templates, you will usually not create a Template directly, but retrieve it from an Engine instance. The Engine allows you to define where the templates are retrieved from when you request them by name.
You can redefine the order of places in the filesystem which are searched for templates, and even define new ways to retrieve templates (i.e, not from the filesystem) by subclassing Grantlee::AbstractTemplateLoader and implementing the loadByName method. For existing loaders, see FileSystemTemplateLoader, InMemoryTemplateLoader, and AkonadiTemplateLoader.