Search code examples
apostrophe-cms

Render Page using ApostropheCMS Language


I know this kind of stupid question to ask . But for beginners and familiar with express nodejs , this question might found useful to others as well. For me , I am familiar rendering nunjucks with this method by using express nodejs. Here is an example that we all know about it :

nunjucks.render('index.html', { foo: 'bar' });

And I found your Apostrophe Docs on this documentation that using render(req, name, data) . I want to customize my cursor and override req.data like using nunjucks above . And I found out that this is the right method to use and I don't know where to start ! Should I use self.beforeShow ? I don't want to use self.route where GET request are taking place. I just want to add additional data and render it on show.html , indexAjax.html or even using a custom indexCustom.html using similar as Nunjucks example above. I know how to do cursor and manipulate the data by it. I'm a slow learner but I never stop learning. Thank you in advance.

P/s : If you guys can post a new tutorial at HOWTO section for this "extra rendering/override data into the page" , that would be extremely helpful !


Solution

  • To make additional data available to your page templates, the easiest way is to listen for the apostrophe-pages:beforeSend promise event (with Apostrophe 2.63.0 or newer):

    // in app.js
    
    var apos = require('apostrophe')({
      shortName: 'myproject',
      // among other things
      modules: {
        'apostrophe-pieces': {}
      }
    });
    
    // in lib/modules/products/index.js
    
    
    module.exports = {
      extend: 'apostrophe-pieces',
      name: 'product',
      construct: function(self, options) {
        self.on('apostrophe-pages:beforeSend', 'getAllProducts', function(req) {
          // Let's assume you have a "products" module that extends pieces
          // and you want all of them on every page (not necessarily a good idea)
          return self.apos.modules.products.find(req).toArray().then(function(products) {
            req.data.products = products;
          });
        });
      }  
    };
    
    {# In any page template or layout #}
    
    {% for product in data.products %}
      {{ product.title }}
    {% endfor %}
    

    The older way is to implement a pageBeforeSend method, but that forces you to use callbacks, and promises are definitely the 2018 way to go.

    You didn't specify anything more about your use case, so my example here is a method that extends pieces in the usual way, but makes sure all the pieces are available on every page - which could be a good idea or a terrible one, depending on how many you have, but it demonstrates the technique.