• Nov 12, 2013

It's much to my chagrin that it took me until this past weekend to properly dive into custom renderers. I had seen them before, primarily when working with mypic, but always avoided building my own, primarily because of what a hassle they are to write. However, I'm now convinced that the hassle is worth it, at least for some primary uses.

If you're not familiar with custom renderers, they're sort of an odd beast, but they're the kind of thing where the concept eventually "clicks" in your mind at some point. In XPages, a component (such as a link, a panel, or an application layout) consists of two main aspects: the structural code that defines the properties of the component and the renderer that handles actually outputting the HTML for the browser. What adding your own custom renderers allows is for you to continue to use the same XSP markup to define the control, yet have very different results.

The best example of this (and the source of most of my education) is the recent Bootstrap4XPages project. It takes a standard OneUI applicationLayout-based app and styles it using Bootstrap markup instead of OneUI, even though the XSP markup is the same. In the normal case, this just means that you can reuse some of the basics when building a Bootstrap-targeted app. And that's good enough on its own: it saves you tons of work.

But the more important aspect is that it lets you focus much more on solving the task at hand and much less on writing to the layout framework.

This is a huge advantage for XPages (and any framework with this separation). As low-key as Bootstrap is (and other modern CSS frameworks are), you still have to structure your markup and sprinkle class names around to match its expectations. With a really fleshed-out set of custom renderers, though, you could potentially not care at all about the resultant UI framework when writing your app and instead focus on using stock or ExtLib controls to solve the problem directly, letting the theme+renderers do the work.

In reality, there'll be a bit of leaking (for example, using Bootstrap-friendly FontAwesome classes instead of images doesn't really fit with standard IBM controls), but I aim to minimize that as much as possible in my future projects. My goal is to use applicationLayout and standard controls for as much as I can, and instead writing a set of custom renderers for each primary theme I want to apply.

I'll have more to write about this later, but for now, the TL;DR version is: custom renderers have the potential to dramatically improve the way XPages apps are written, as long as you're willing to do the initial Java legwork.

Nov 12, 2013
Tim Tripcony

When you consider also that renderers don't have to send HTML in the first place - we just tend to assume that they do - the possibilities are endless. Imagine setting an existing app to use a different theme, and suddenly all the output is JSON. Or ODF. Or SVG. Or PDF. Or anything you can dream up. Fun for the whole family.

Nov 12, 2013
Jesse Gallagher

Yeah, I thought about that as well, including with HTML-adjacent languages like XUL (if you're targeting Gecko alone). In the right kind of app, you could end up using the same XSP markup for, say, both the UI view display and the XLSX export.

Nov 12, 2013
Tim Tripcony

Right, exactly... and it doesn't just have to be the theme that controls the behavior. The rendererType attribute can be computed dynamically (say, for instance, based on the compositeData passed to a Custom Control, user agent, permissions, etc.) or set at runtime via an event. The closest I ever came to writing an entire custom render kit was a library that just referenced a URL query string parameter: if the magic parameter was there, everything came back as JSON; otherwise, it just deferred to the default renderers, which was what allowed precisely what you alluded to: a given app might only contain one XPage, but generate entirely different content based on whether the consumer was a standard desktop browser, a mobile device, or some other app consuming the content as an API.

As you indicated above, it's a fair bit of investment to do this for every component, but what we found to be effective at the time was to start with the most "important" components and gradually address the rest as needed. You can fairly rapidly build up quite a bit of momentum once you accumulate some reusable (and extensible) code, and get a feel for what patterns work best based on the type of output you're attempting to achieve.

Nov 13, 2013
Nathan T. Freeman

Custom Renderers are cool. Now stick this in your head: PIPELINED renderers

Yeah, I know... mind. blown. :-)

Post New Comment