Custom template for a particular topic



  • Is it possible to have a custom template for a particular topic (identified by a topic id)? Something like topic_tid.tpl somewhere in a plugin or theme? My intention is to be able to theme a specific topic and leave the remaining use the default topic template.


  • Admin

    Unfortunately I think that might be a bit out of the realm of possibility (though I could be wrong!)

    It sounds like you're trying to create a distinct page... would the custom-pages plugin do what you need?



  • @julian Thank you for replying. I am thinking of a small hack in that case. Let me know if this will work. What if I create a custom route and use a modified version of the original topic.tpl as its template?

    
    var controllers = require('./lib/controllers'),
    plugin = {};
    
    plugin.init = function(params, callback) {
    	var router = params.router;
    	var middleware = params.middleware;
    
      // Define the function that renders the custom route.
    	function render(req, res, next) {
    
    		// Get data object corresponding to the specific topic. The topic ID is fixed.
    		var data;
    
    		// This is the path to your template without the .tpl, relative to the templates directory in plugin.json
    		var template = 'my-custom-page'
    
    		// Send the page to the user.
    		res.render(template, data);
    	}
    
    	// This actually creates the routes, you need two routes for every page.
    	// The first parameter is the actual path to your page.
    	router.get('/my-custom-page', middleware.buildHeader, render);
    	router.get('/api/my-custom-page', render);
      
    	callback();
    };
    
    module.exports = plugin;
    

    'data' needs to be filled with information about a specific topic. If this is possible, then how can I get the data object corresponding to a particular topic in the render function? Is there some function that can take a topic id as input and just return 'data'?


  • Admin

    @aneeeshp You can call https://github.com/NodeBB/NodeBB/blob/master/src/controllers/topics.js#L19 and get the topic data. It would look something like this

    function render(req, res, next) {
        req.params.topic_id =  "123"; // id of topic to load
        res.locals.isAPI = true; // so the function below returns json data instead of rendering the template
        topicsController.get(req, res, function (err, data) {
    
    	// This is the path to your template without the .tpl, relative to the templates directory in plugin.json
    	var template = 'my-custom-page'
    
    	// Send the page to the user.
    	res.render(template, data);
        });
    }
    

  • Admin

    Actually my previous method won't work, that method either renders the template or does res.json(data) so the callback won't be called. However you can still call the topic route server side via request.

    function render(req, res, next) {
        request(nconf.get('url') + '/api/topic/' + topicId, { json: true}, function (err, res, data) {
    
    	// This is the path to your template without the .tpl, relative to the templates directory in plugin.json
    	var template = 'my-custom-page'
    
    	// Send the page to the user.
    	res.render(template, data);
        });
    }
    

  • Global Moderator

    Here's another way of doing it:

    1. Copy topic.tpl from persona into your custom theme (assuming you have one)
    2. Modify it by wrapping the whole thing in the following:
    <!-- IF function.equals(tid, "[topic id number]") -->
    [your custom topic template here]
    <!-- ELSE -->
    [original topic template]
    <!-- END -->
    
    1. Add an equals helper as described here and here


  • Thank you all for the suggestions. I tried @PitaJ `s solution. This is what I have done:

    In library.js in my custom theme, I added:

    benchpress.registerHelper('isTaskList', function (post) {
            return post.tid === 1090;
    });
    

    In lib/persona.js in my custom theme, in the $(document).ready event, i added:

    templates.registerHelper('isTaskList', function (post) {
            return post.tid === 1090;
    });
    

    And then in the templates/partials/topic/post.tpl, I have used:

    <!-- IF function.isTaskList -->
    

    as the condition

    The condition is working as expected when the page is initially loaded for the posts that are loaded/displayed initially, however when I scroll down and when the further posts are getting loaded/displayed at the bottom of the page, the condition is not taking into effect. Could you please advise if something is missing?


  • Global Moderator

    @aneeeshp have you tried clearing your cache or putting a console.log statement in your helper client-side?



  • @pitaj Thank you. Issue was with the condition. I have used condition as shown below which solved the problem.

    post.posts[0].tid === 1090
    


  • Such a great post to know different useful information.


 

Suggested Topics

| |