Report call our api beforeRender for only one report
-
Hi,
Can a jsreport template call our api to pull data instead of having to push data to it?
I understand that there is the beforeRender event that runs in nodeJS with all templates, how can I have it executed for only one template because the call will be different based on input parameters and context.
Also is there a way to include scripts to the beforeRender so that they simply call our api instead of copy pasting code?
-
Can a jsreport template call our api to pull data instead of having to push data to it?
I understand that there is the beforeRender event that runs in nodeJS with all templates, how can I have it executed for only one template because the call will be different based on input parameters and context.yes, you can pull data in a jsreport script. scripts can run globally (for all templates) or just in the scope or just one template, in studio you can choose which scripts should run in the context of your template:
there is an example called
Orders
that is present in every jsreport installation, this example shows how to call a remote API to pull data to use in the jsreport pipeline.example
Orders scripts
(if you are going to try it in your server make sure to allow thehttp
module in your jsreport configuration):// custom server side script used to fetch data from remote REST API var http = require('http'); function getOrders(country, cb) { http.get({ hostname: 'services.odata.org', port: 80, path: `/V4/Northwind/Northwind.svc/Orders?$filter=${encodeURI(`ShipCountry eq '${country}'`)}`, }, (result) => { var str = ''; result.on('data', (b) => str += b); result.on('error', cb); result.on('end', () => cb(null, JSON.parse(str))); }); } function beforeRender(req, res, done) { // the report parameter country can be send from the client API request req.data.country = req.data.country || 'France' getOrders(req.data.country, (err, json) => { if (err) { return done(err); } var orders = json.value; var ordersByQuarter = {}; orders.forEach((o) => { o.OrderDate = new Date(o.OrderDate); var key = o.OrderDate.getFullYear() + '/' + (o.OrderDate.getMonth() + 1); ordersByQuarter[key] = ordersByQuarter[key] || { value: 0, orderDate: o.OrderDate }; ordersByQuarter[key].value++; }); req.data.orders = orders; req.data.accumulatedOrders = ordersByQuarter; done(); }); }
in this script you can see how we use the
getOrders
function inside thebeforeRender
,getOrders
gets data from a remote API (using node.jshttp
module) and set the returned data toreq.data.orders
, which will be used when rendering the template. you can do it in the same way for your case but taking into account any previous input/parameter that you provide, this will help you to prepare your request for the remote API that you want to consume.Also is there a way to include scripts to the beforeRender so that they simply call our api instead of copy pasting code?
for example you can put the
getOrders
function in an asset, then in your script import the asset and use the function insidebeforeRender
function normally. that would help you to avoid repeating code.