Search code examples
apostrophe-cms

How to access widget properties/parameters inside a widget template in Apostrophe cms


I was playing with Apostrophe CMS, and tried to create a widget which gets some values from a third party API based on its settings. Is there any way I could retrieve the values of the widget inside the widget index.js? Basically when the admin creates a page, he will add a widget with some values set. And the widget behavior should change based on those settings. Is this possible at all and if it is then how?

const request = require('request-promise');

module.exports = {
    extend: 'apostrophe-widgets',
    label: 'Listing widget',
    addFields: [
        {
            name: 'page',
            type: 'integer',
            label: 'Page',
            required: true
        },
        {
            name: 'count',
            type: 'integer',
            label: 'Count',
            required: true
        }
    ],
    construct: function(self, options) {
        self.on('apostrophe-pages:beforeSend', 'preset', async function(req) {
            var page = ...;
            var count = ...;
            const dataToList = await request({
                uri: "someURL?count=" + count + "&page=" + page,
                json: true
              });
            req.data.dataToList = dataToList;
        });
    }
};

I my code you can see a very basic widget. The only thing I need is to get somehow the values for page and count variables.

Update: Based on Stuart Romanek's advice, the corrected, final code looks like this:

const request = require( 'request-promise' );

module.exports = {
    extend: 'apostrophe-widgets',
    label: 'Listing widget',
    addFields: [
        {
            name: 'page',
            type: 'integer',
            label: 'Page',
            required: true
        },
        {
            name: 'count',
            type: 'integer',
            label: 'Count',
            required: true
        }
    ],
    construct: function( self, options )
    {
        const superLoad = self.load;
        self.load = ( req, widgets, callback ) => superLoad( req, widgets, async ( err ) =>
        {
            if( err )
            {
                return callback( err );
            }

            for( const widget of widgets )
            {
                var page = widget.page;
                var count = widget.count;

                const dataToList = await request( {
                    uri: "http:/APIRoute?count=" + count + "&page=" + page,
                    json: true
                } );

                widget.dataToList = dataToList;
            }
            return callback( null );
        } );
    }
};

And from the HTML it can be accessed with: data.widget.dataToList.


Solution

  • If you want to do something to a widget before it renders on a page you can hook into the widget's load method in it's index.js

    module.exports = {
      name: 'my-widget',
      label: 'My Widget',
      construct: (self, options) => {
        const superLoad = self.load;
        self.load = (req, widgets, callback) => superLoad(req, widgets, (err) => {
          if (err) {
            return callback(err);
          }
    
          // Hit some API, do something wacky
    
          for (const widget of widgets) {
    
            // do something to each widget
    
            widget.coolThing = true;
          }
          return callback(null);
        });
      }
    };
    

    https://docs.apostrophecms.org/apostrophe/modules/apostrophe-widgets#load-req-widgets-callback

    In load, widgets is an array widgets of this type being loaded up on this request. Here you can figure out of if you want to add something to the widget's data. You can access this information in your template and front-end js.