Just released: jsreports 1.4.87

Quick update: we just released version 1.4.87 of jsreports! You’ll notice some visual updates to the designer’s look and feel, plus a bunch of other improvements throughout the product.

If you’re looking for the new element menu, it’s been moved into a menu button in the left margin of the template, leaving more room for the template itself.

We’re also expanding what you can do with data sources, allowing you to define data sources that depend on (and transform) other data sources.

Expect more updates to the designer in the coming months.

Version 1.4.75 released

Here are some of the new features available today in version 1.4.75.  Download the free trial here: https://jsreports.com/trial.

  • New features for table rendering in PDF: background images, cell padding
  • Improved handling of large text blocks including Markdown bullet lists and page breaking in PDF
  • Improved support for nested JSON data structures via dot syntax (“row.field1.field2”) and autocomplete
  • Default element properties
  • New Line element
  • Multiple data sources and multiple detail sections per data row
  • And more!  See the release notes here: https://jsreports.com/docs/changelog

 

ES6 classes are pretty handy for extensibility

ES6 introduced syntax sugar for something a lot of people were already doing in ES5, namely simulating classical object-oriented inheritance.  That move got some blowback from people who say that prototypal inheritance is better, or classes are terrible.  And it’s true that classes aren’t really a natural part of JavaScript.

We had a scenario recently though where we found that ES6 classes were a good fit.  We were adding the ability to define your own custom elements in jsreports.  These are basically custom components that leverage built-in behavior and add their own logic too.  For example, you can define a checkbox component with a boolean “checked” property that toggles based on a data calculation (this is actually one of the examples we provide, because it’s so simple).

Here are some of the advantages we found when using classes:

  • The ES6 class syntax is concise and easy to read; it’s easy to take a class we provide and pretty easily see where the natural extension points are.  The class structure is a good way for our code to self-document what it is and how it relates to other components.
  • Classes are a good match when the thing you’re modeling already has an “is-a” relationship.  In our case, custom elements are natural subclasses of an abstract Element type that already has many concrete implementations.
  • Having a built-in class syntax allows you to “say what you mean” in the code, instead of piecing together a bunch of functions and prototypes manually.  On top of the human readability advantage already mentioned, this opens the door to better documentation generation and tooling.

But there are some things to watch out for, too:

  • The explosion of subclasses.  In a way, classes provide the perfect trap for programmers who are already tempted to over-abstract things.  The antidote (for us) is to keep class hierarchies shallow and class count low, and tend toward composition where possible.
  • Since this is just sugar, it’s important to have a good understanding of how concepts like statics and visibility work in the underlying JavaScript.  If your experience with classes comes from a language like Java or C#, there are some surprises in store.
  • ES6 doesn’t support interfaces, which would be helpful in our scenario.

Now, not all of our customers are using an ES6 environment yet.  We still provide our pre-built bundles in ES5, but we also ship (to customers) our Babel build chain and ES6 source.

We’re pretty happy with how well it’s worked out so far.

For more on ES6 classes, see https://hacks.mozilla.org/2015/07/es6-in-depth-classes/.

Useful thoughts on API design and classes can be found in Joshua Bloch’s classic presentation “How to Design a Good API and Why It Matters.”

Announcing jsreports + Sencha ExtJS integration

Do you use Sencha’s ExtJS framework and need to generate printable reports from your data? We just released a jsreports integration with ExtJS that you should check out.

Screen Shot 2016-08-09 at 12.03.57 AM

We provide two new ExtJS components, Viewer and Designer, that encapsulate those two jsreports modes. That makes it super easy to drop them into an existing ExtJS app.

What’s more, you can use your existing ExtJS data stores as data sources for the reports. So your existing data models provide the schema and you don’t need to do anything else. Let ExtJS handle the data fetching for you.

A demo with source code is here:
https://jsreports.com/examples/extjs/

Documentation is here:
https://jsreports.com/docs/extjs/#!/api/jsreports.integrations.extjs.Designer

Get in touch via email at support@jsreports.com to let us know what we should add next!

Version 1.4.40 released with new designer features

We just released version 1.4.40 with a slate of updates across the product. Some important changes are in the designer, including:

– Fonts are now scaled in the template to better represent their size in the final output
– You can hide the left settings pane using config option showSettingsPane: false
– You can define your own pre-configured elements and put them in the toolbar for use in reports

On that last one, we’ll have a demo out next week that shows how to implement your own custom controls. We’re just getting started in this area and have big plans for this feature.

See the whole list of changes at the changelog .

Demo: Rendering reports on the server with Node.js and jsreports

Here’s a quick example of how to run reports on the server using Node.js.  The way it works is simple:

  1. Import the jsreports-server module from the jsreports distribution,
  2. Load your report definition and data source JSON files just like you would in the browser, and
  3. Call server.export() on a new Server instance.

Important: before running your script, you’ll need to install the phantomjs-prebuilt package:

npm install -g phantomjs-prebuilt

Here’s some sample code showing how easy it is:

var fs = require('fs');
var path = require('path');

// Import the jsreports server package
var jsreports = require('./lib/jsreports/jsreports-server.js');

var server = new jsreports.Server();

// Load the report from a .json file on disk
var report = require('./reports/report.json');

// For demo purposes only; returns an array of data source configurations, just as in the browser
var datasets = require('./datasets.js');

// Call server.export() just like you would call jsreports.export() in the browser
server.export({
   format: 'PDF',
   report_def: report,
   datasets: datasets,
   // Must provide a file:// base URL to prepend to the image URLs in the report, 
   // in order to locate them on the server - here, use the current directory
   imageUrlPrefix: 'file://' + path.resolve(__dirname) + '/'
}, function(err, pdfStream) {
  if (err) return console.error(err);
  // Got the output stream - write PDF to file
  var outPath = path.resolve(__dirname, 'out-' + (new Date()).getTime() + '.pdf');
  var outStream = fs.createWriteStream(outPath, 'utf8');
  pdfStream.on('end', function() { 
    console.log('Wrote PDF to', outPath);
    server.stop();
  });
  pdfStream.pipe(outStream);
});

Call server.stop() when you’re done rendering.  If you don’t, the Server instance will remain running to serve future requests.  By default, up to 3 worker processes will handle reports in parallel as needed.

As always, get in touch with us at support@jsreports.com if you have any questions!