How to show a widget in a theme widget area ?

Moved Technical Support
  • Hello I'm facing a problem. I have defined in my theme a new Widget Area via the library. The area is displayed in ACP and I can add a widget in it. But I haven't figured out how to display it in my actual theme.

    What I've done is in theme.js (library) added this in Theme.defineWidgetsAreas.

    {
    	'name': 'Menu',
    	'template': 'menu.tpl',
    	'location': 'menu'
    }
    

    In menu.tpl I've added <div widget-area="menu"></div> as I've seen this for sidebar in category.tpl and topic.tpl for instance.
    Since my menu.tpl is a partial I've tested to change 'template': 'menu.tpl' to 'template': './partials/menu.tpl' but it didn't change anything.

    What I am doing wrong ? I'm pretty sure it's on the template line that the error exist cause it shows correctly on ACP.
    Need some help here, thanks in advance.

    On another note, I've tried to use the theme library like a plugin one and it seems that hook:static.app.load cause NodeBB to never finish rendering theme. It shows info: [themes] Successfully compiled templates. but nothing happens after (sockets, js and css minification and finally NodeBB ready).

  • Will defer to @psychobunny for the widget questions.

    As for static:app.load, don't forget to call callback(); at the end!

    The full method:

    var myMethod = function(app, middleware, controllers, callback) {
      app.get('/example', function(req, res) {
        res.send('hello!');
      });
    
      callback();
    });
    
  • @julian Thanks it was the callback() missing.
    Another question regarding templates this time. I get data from a request and I want to pass it to a template.
    My data is working, I can see it with console.log.
    I'm using templates.parse('templates/partials/categories_list.tpl',{categories: data}) to link the data to my template.
    But I have no idea of how to see if this is really doing something (if there's a /api route created). And since it doesn't work and I can't know why it's a bit tricky to figure out.
    Thanks in advance for future help.

  • I think its just templates.parse('partials/category_list.tpl', {categories: data}, callback);

  • @baris I tried that as well and it didn't work.

  • Bumping this thread with more information :

    This is my structure

     static/lib/theme.js
     templates/partials/categories_list.tpl
    

    I want to call templates.parse on categories_list.tpl

    In categories_list.tpl I have this to test :

    TEST
    <!-- BEGIN categories -->
    INSIDE CATEGORIES
    {categories.name}
    <!-- END categories -->
    

    I have just managed to show TEST, which means that the data isn't parsed in the template.

    I've tried

    templates.parse('templates/partials/categories_list.tpl', {categories: data}, callback);
    templates.parse('/partials/categories_list.tpl', {categories: data}, callback);
    templates.parse('partials/categories_list.tpl', {categories: data}, callback);
    templates.parse('../../templates/partials/categories_list.tpl', {categories: data}, callback);
    

    None worked out.
    data is a working object and I can console.log it, so the big deal is the templates.parse function.

  • I've finally managed to get it working I was totally wrong on how I thought it was working and that's why it wasn't giving me what I expected.

    I thought that templates.parse was actually interpreting the file and displaying it but that's absolutely not the case. It takes a string and parse it with the template engine based on the object you give.

    So after loading my file, getting it's data parsing it I have a nice html code but I don't know how to use it 😞

    I imagine I have to send this as a string and use jQuery to append it somewhere but I don't know what is the best way of doing this. In my previous plugins I was sending data to /api/plugin but in this case it's not the good thing to do since it's not an object. Is there a way to send a string via NodeJS and get it in front to actually show it ?

  • templates.parse can be used by passing a file name as the first param, but I don't think you need to pass the .tpl extension. At least that's how it's used in core. Once it parses it passes back html which we then add to DOM using jquery.

  • @baris So if I understand I need to do all of this in a front script. My problem is that I want to use
    categories.getCategoriesByPrivilege(app.uid, 'find', function(err, data){}

    I think I can use require to actually use categories but I won't have the app.uid info which is needed. Or is there a way to use this in front scripts ?

    Tell me if I'm wrong but I see the solution like this :

    • In my lib I get the data object provided by categories.getCategoriesByPrivilege
    • I use res to send it to some /api/ address
    • In a front script I retrieve this data
    • I use the parse function to transform it in html
    • I append it using Jquery

    My only question is how can you use parsing function in front file ? module is not defined so templates = module.parent.require('templates.js') wont work is there another way to call this function ?

    Thanks for your help.

  • @esiao good question, @psychobunny recently removed the templates.js from core so it is a npm module now, not sure how it is used from client side right now. Will wait for him to chime in on that.

    In my lib I get the data object provided by categories.getCategoriesByPrivilege
    I use res to send it to some /api/ address
    In a front script I retrieve this data
    I use the parse function to transform it in html
    I append it using Jquery

    This sounds right.

  • There should be a global object attached to the window called templates (same with app and ajaxify, some methods in there could be useful to you as well)

    Also the template is automatically loaded for you as well in the same step.

    templates.parse(template, data, callback);

  • @psychobunny, @baris Thank you I'll try that out tommorow. Going to sleep 💤

  • @psychobunny window.ajaxify.loadTemplate is broken. Object window.ajaxify returns it as a function but when in use there's a Uncaught TypeError: undefined is not a function error.
    And console.log(window.ajaxify.loadTemplate) returns undefined.
    @Schamper has the same problem with his plugin cards : https://community.nodebb.org/topic/2495/so-the-acp-doesn-t-work-on-master/7

    While I don't think I need it cause templates.parse do the same job I wanted to see what you meant by using ajaxify 🙂

  • works for me, although as you say, templates.parse is what you should be using instead, ajaxify.loadTemplate will be changed to a private function eventually

    window.ajaxify.loadTemplate('login', function(data) {
        console.log(data);
    });
    

    this works for me, it will explode if
    A- your template doesn't exist or in your case
    B- you don't pass the template string in

  • I've managed to do what I wanted to do, thanks for your help 👍

  • @psychobunny said in How to show a widget in a theme widget area ?:

    window.ajaxify.loadTemplate

    This isn't the case anymore, rite? Any other ways to expose ajaxify to scripts in the custom header?

    Cheers.

  • Answer to self: enable the custom header and the global vars will be there. Sounds about right?


Suggested Topics