You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
6.1 KiB
ReStructuredText
194 lines
6.1 KiB
ReStructuredText
Rendering Engine
|
|
=================
|
|
|
|
How it works
|
|
------------------------------------------------------
|
|
|
|
Every page has an associated API call, Template file, and Language File.
|
|
|
|
For example, if you navigate to `/topic/351/nodebb-wiki <http://community.nodebb.org/topic/351/nodebb-wiki>`_, the application will load three resources. The API return `/api/topic/351/nodebb-wiki <http://community.nodebb.org/api/topic/351/nodebb-wiki>`_ and the `template <http://community.nodebb.org/templates/topic.tpl>`_, in this example, "topic.tpl", and the appropriate `language file <community.nodebb.org/language/en_GB/topic.json>`_ "topic.json"*.
|
|
|
|
Just prepend api/ to the URL's path name to discover the JSON return. Any value in that return can be utilized in your template.
|
|
|
|
*A page's name corresponds to the template and language's filename (ex. ``http://domain.com/topic/xyz`` correlates to ``topic.tpl``). Sometimes this is not the case - ex. ``/user/xyz`` loads ``account.tpl``. Have a look at the ``custom_mapping`` section in ``public/templates/config.json`` for more details.
|
|
|
|
Templating Basics
|
|
------------------------------------------------------
|
|
|
|
Using the API return as your guide, you can utilize any of those values in your template/logic. Using the above API call as an example, for anything in the root level of the return you can do something like:
|
|
|
|
.. code:: html
|
|
|
|
{topic_name}
|
|
|
|
To access values in objects:
|
|
|
|
.. code:: html
|
|
|
|
{privileges.read}
|
|
|
|
And finally you can loop through arrays and create blocks like so:
|
|
|
|
.. code:: html
|
|
|
|
<!-- BEGIN posts -->
|
|
{posts.content}
|
|
<!-- END posts -->
|
|
|
|
|
|
The above will create X copies of the above block, for each item in the posts array.
|
|
|
|
Templating Logic
|
|
------------------------------------------------------
|
|
|
|
NodeBB's templating system implements some basic logic. Using the same API call as above for our example. You can write IF conditionals like so:
|
|
|
|
.. code:: html
|
|
|
|
<!-- IF unreplied -->
|
|
This thread is unreplied!
|
|
<!-- ENDIF unreplied -->
|
|
|
|
|
|
Another example:
|
|
|
|
.. code:: html
|
|
|
|
<!-- IF !disableSocialButtons -->
|
|
<button>Share on Facebook</button>
|
|
<!-- ELSE -->
|
|
Sharing has been disabled.
|
|
<!-- ENDIF !disableSocialButtons -->
|
|
|
|
|
|
We can check for the length of an array like so:
|
|
|
|
.. code:: html
|
|
|
|
<!-- IF posts.length -->
|
|
There be some posts
|
|
<!-- ENDIF posts.length -->
|
|
|
|
|
|
While looping through an array, we can check if our current index is the @first or @last like so:
|
|
|
|
.. code:: html
|
|
|
|
<!-- BEGIN posts -->
|
|
<!-- IF @first -->
|
|
<h1>Main Author: {posts.username}</h1>
|
|
<!-- ENDIF @first -->
|
|
{posts.content}
|
|
<!-- IF @last -->
|
|
End of posts. Click here to scroll to the top.
|
|
<!-- ENDIF @last -->
|
|
<!-- END posts -->
|
|
|
|
|
|
For more advanced documentation, have a look at the `templates.js <https://github.com/psychobunny/templates.js>`_ repository
|
|
|
|
|
|
Exposing template variables to client-side JavaScript
|
|
------------------------------------------------------
|
|
|
|
There are two ways of letting our JS know about data from the server-side, apart from WebSockets (TODO: will be covered in a different article).
|
|
|
|
Via jQuery.get
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
If we require data from a different page we can make a ``$.get`` call to any other API call. For example, if we wanted to know more about a specific user we could make a call like so:
|
|
|
|
.. code:: javascript
|
|
|
|
$.get(RELATIVE_PATH + '/api/user/psychobunny', {}, function(user) {
|
|
console.log(user)
|
|
});
|
|
|
|
|
|
See this API call in action: http://community.nodebb.org/api/user/psychobunny
|
|
|
|
Via Template Variables
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
In topic.tpl for example, we can add a hidden input like so:
|
|
|
|
.. code:: html
|
|
|
|
<input type="hidden" template-variable="pageCount" value="{pageCount}" />
|
|
|
|
The template system will immediately parse all of these and expose them via the following method:
|
|
|
|
.. code:: html
|
|
|
|
ajaxify.variables.get('pageCount');
|
|
|
|
This is the ideal method of letting JS know about important variables within the template.
|
|
|
|
Internationalization
|
|
---------------------
|
|
|
|
The template engine interfaces with the internationalization system as well. We can embed variables into language strings. Let's use `this API call <http://community.nodebb.org/api/register>`_ as well as this `language file <http://community.nodebb.org/language/en_GB/register.json>`_ as an example. We can now do something like the following:
|
|
|
|
.. code:: html
|
|
|
|
[[register:help.username_restrictions, {minimumUsernameLength}, {maximumUsernameLength}]]
|
|
|
|
Which will translate this string:
|
|
|
|
.. code:: html
|
|
|
|
A unique username between %1 and %2 characters
|
|
|
|
to
|
|
|
|
.. code:: html
|
|
|
|
A unique username between 2 and 16 characters
|
|
|
|
Advanced Topics
|
|
---------------------
|
|
|
|
Dynamically requiring and rendering a template file from client-side JavaScript
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
The template engine lazy loads templates on an as-needed basis and caches them. If your code requires a template or partial on-demand then you can :
|
|
|
|
.. code:: javascript
|
|
|
|
ajaxify.loadTemplate('myTemplate', function(myTemplate) {
|
|
var html = templates.parse(myTemplate, myData);
|
|
});
|
|
|
|
|
|
You can also access the invidual blocks inside each template, which is handy for doing things like (for example) rendering a new post's ``<li>`` and dynamically sticking it in an already loaded ``<ul>``
|
|
|
|
.. code:: html
|
|
|
|
Some stuff here...
|
|
<!-- BEGIN posts -->
|
|
We just want to pull this block only.
|
|
<!-- END posts -->
|
|
... some stuff here
|
|
|
|
.. code:: javascript
|
|
|
|
ajaxify.loadTemplate('myTemplate', function(myTemplate) {
|
|
var block = templates.getBlock(myTemplate, 'posts');
|
|
var html = templates.parse(block, myData);
|
|
});
|
|
|
|
|
|
Rendering templates on server-side Node.js
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
The templating system hooks into Express just like most other templating frameworks. Just use either ``app.render`` or ``res.render`` to parse the appropriate template.
|
|
|
|
.. code:: javascript
|
|
|
|
res.render('myTemplate', myData);
|
|
|
|
.. code:: javascript
|
|
|
|
app.render('myTemplate', myData, function(err, parsedTemplate) {
|
|
console.log(parsedTemplate);
|
|
}); |