NexJ Logo

AFL portlets

AFL portlets and controls let you work directly with JavaScript, CSS, and HTML. They leverage AFL core libraries for portal lifecycle management, data binding, context bus management, control development, internationalization and more.

AFL - Application Foundation Layers

AFL is a JavaScript platform for building applications. It provides the following subsystems:

  • Cross-platform UI framework using semantic, mostly-declarative API, with client-side state management and a stateless server tier support for scalability.
  • Cross-platform UI toolkit providing common UI controls.
  • DOM-based UI toolkit plug-in for rendering on web browsers, with theme support.
  • Context bus plug-in for portalized communication between UI components.
  • NexJ Portal API bridge.
  • RPC framework with asynchronous batch request support for counteracting network latency.
  • Business logic framework providing a Service-Oriented Architecture (SOA) for implementing server-side functionality.
  • Date/time calculation API with complete time zone support and tools for automatic time zone database generation.
  • Internationalization (I18N) framework with configurable formatters and parsers for common data types and support for custom data formatting and parsing, languages with changing word forms and bidirectional scripts.
  • And more.

Among other things, we use it to build UI.

Portlets

A portlet is a UI view (control) that can contain child controls and supports the portal bus. With AFL portlets, you can build any portlet pattern provided by MDA portlets (lists, details, charts, and so on), but since you are simply working with JavaScript, CSS, and JavaScript libraries, you have more flexibility to implement less common patterns.

MDA portlet rendering

MDA portlets, that is, those defined with the Model Definition Language, are rendered as AFL portlets before they are sent to the browser. They are defined in simple XML elements that specify the portlet layout, binding, and behaviors, then rendering code creates AFL JavaScript that runs in your browser. You can see this by inspecting the application source with your browsers developer tools.

An AFL portlet is really just a module that returns a portlet control that, in turn, typically contains a card control, with logic, and bindings, and other controls.

return function() { 
	return ui("Portlet", {children: [ui("Card", {...
};

AFL portlets are typically saved in mod/app/<portletName>.js and are available at <server-root>/ui/<portletName>. Any CSS rules specific to the portlet are saved alongside the module in mod/app/<portletName>.css.

Controls

AFL controls are modules that contain a view definition (properties, behaviors) and a renderer to generate the control's HTML, CSS, and JavaScript. Renderers may use AFL libraries or React. The AFL core libraries contain a rich set of pre-built controls (many are in the `nexj/ui` and `nexj/ui/core` modules). If you have the demo app running, try looking at http://localhost:7080/training/ui/demo for examples of some of the pre-built controls. You will see charts, cards, tabs, and complex composite controls like the schedule.

For React Developers

For React developers, think component when you hear module.

AFL portlets and control definitions are simply modules. The following section discusses their structure. 

Module structure

Modules begin with their name and a list of dependencies. The module dependency system is based on the Asynchronous Module Definition (AMD) specification.

/** Sample Module */ 
define("app/mysample", ["nexj/sys", "nexj/ui", "nexj/ui/core", "nexj/ui/obj", "nexj/ui/bus"], 
	function(sys, ui) {"use strict"; 
		return function() { 
			return ui("Portlet", {children: [ui("Card", {...
		};
	}
);

A module always contains the define(); function. It takes three parameters:

  • The module name, for example, "app/mysample" (must match the file name of the module in your project's mod folder. "/" in the name represents either the folder structure or a "." in the name).

  • Dependencies, which is a list of modules and module mix-ins that this one depends on

  • A function that takes the dependent modules as parameters and returns a function that returns a view (typically a portlet for portlet modules).

In this example, the module name is "app/mysample" and the module should be saved in the mod/app/mysample.js file.

The dependencies are ["nexj/sys", "nexj/ui", "nexj/ui/core", "nexj/ui/obj", "nexj/ui/bus"]

The function takes sys and ui as parameters which map to the contents returned from "nexj/sys", "nexj/ui". The other dependent modules are mix-in extensions for these three modules. The function returns a function that returns a ui("Portlet", ... object. This portlet object has some layout properties and a collection of child controls.

These controls, in turn, have their own module definitions with a view definition and a renderer. These are maintained in separate files by convention. The typical arrangement is:

  • mod/nexj/ui.mySampleControl.js - where the control's view is maintained. This includes the control's properties and behaviors.
  • mod/nexj/ui.mySampleControl.dom.js - where the control's renderer is maintained. A control's renderer can be coded using:
    • The AFL dom renderer which uses JSONML for the layout,

    • Or the AFL React renderer, which allows you to write your rendering, and most of your control, in React.

  • mod/nexj/ui.mySampleControl.css - where any control-specific css rules are maintained


This arrangement is for modularity only. The view and rendering code may be maintained in the same .js file, if desired.