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 `_, the application will load three resources. The API return `/api/topic/351/nodebb-wiki `_ and the `template `_, in this example, "topic.tpl", and the appropriate `language file `_ "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 {posts.content} 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 This thread is unreplied! Another example: .. code:: html Sharing has been disabled. We can check for the length of an array like so: .. code:: html There be some posts While looping through an array, we can check if our current index is the @first or @last like so: .. code:: html

Main Author: {posts.username}

{posts.content} End of posts. Click here to scroll to the top. For more advanced documentation, have a look at the `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 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 `_ as well as this `language file `_ 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 ``
  • `` and dynamically sticking it in an already loaded ``
      `` .. code:: html Some stuff here... We just want to pull this block only. ... 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); });