Jello framework

Jello's RESTful API together with it's powerful authorization model makes it an ideal framework for developing web services. Developing a front-end user interface is the next logical step towards a complete end-to-end application.

With Jello, you can choose (or mix) between several implementation options. From instant, out-of-the-box data views, to pixel perfect UI.

- Instant data views

- UX Annotations

- Built-in controls

- Custom controls

- Custom views

- Custom UX annotation

- Pixel perfect custom UI

- Client data views API

- Reusable Jello modules



Jello offers a unique out-of-the-box data views feature in addition to the OData protocol. By simply replacing the protocol /jello/data/ prefix with /jello/view/ you will get UI views so you can test your application and start to interact with the data instantly. These views can also serve as Admin UI and can be easily extended by adding custom controls.


 out-of-the-box data view

View options:

- $showRecordDetail

- $embeddedRecordDetail

- $embeddedRecordDetail image|fileName|fileSize|key

- $resourcePath


By using jello.ux annotations, you can append UX metadata to your elements. This additional information will be exposed in the metadata document via REST calls. Jello Views supports the following core UX annotations:


@Label (jello.ux.Label)

Provide a label for entities, fields, enumerations, and actions' parameters.

Example:
1
2
@Label("Release year")
private Integer year;

@Hint (jello.ux.Hint)

Provides a hint for fields and actions' parameters.

Example:
1
2
@Hint(value="Must be unique", displayAs=Display.PLACEHOLDER)
private String licensePlate;

@Validation (jello.ux.Validation)

Jello data form validates field values based on the field data type. In addition, you can specify more validations such as min/max for numbers, min/max length for strings, and special patterns such as url or email.

Example:
1
2
3
4
5
@Validation(min=0,max=1000)
public Double price;

@Validation(email=true)
public String email;


@Control (jello.ux.Control)

By adding @Control annotation to a field or action's parameter, you can hide specific controls or bind a field to a control type other than the default one associated with the field type.

This non-default control can be either a Jello UX extension control or a custom control.

Jello UX extension controls:
- prefixed with jello.ux.controls.

- Currently supported:

  • jello.ux.controls.TreeSelector
  • jello.ux.controls.TextareaCtrl
  • jello.ux.controls.RatingControl
  • jello.ux.controls.CheckboxCtrl
  • Custom controls:
    - Absolute path to the control resource.
    - See Custom controls for more details.

    Example:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    @Control(hide=true)
    public String preview;
    
    @Control(src="/demo/custom/ratingControl")
    Integer rating;
    
    @Expose @Reference(Category.class)
    @Control(
       //Using jello tree selector control instead of the default dropdown 
       src="jello.ux.controls.TreeSelector", 
       // Applies only for data form, not data table 
       containerRole=ContainerRole.FORM, 
       settings={
          "parent:parent", 
          "children:children",
          "label:name",
          "icon:icon"
       }
    )
    public Key category;
    
    @Control(src="jello.ux.controls.TextareaCtrl", settings={"rows:5"})
    public String comment;
    

    Conditional state:
    Sometimes it is desired to hide or disable control based on a dynamic value from another field. Such behavior can be defined by using one of the @Control hideIf, showIf, enableIf, disableIf optional fields with the following syntax:

    @Control(hideIf|showIf|disableIf|enableIf="JS-EXPRESSION")

    Example:
    1
    2
    3
    4
    5
    6
    7
    8
    @Control(hideIf="rating == 3")
    public Boolean hideIfRating3;
    
    @Control(showIf="color == 'GREEN'")
    public Boolean showOnlyIfColorGreen;
    
    @Control(enableIf="color == 'GREEN'  && year > 1990")
    public Boolean enableOnlyIfColorGreenAndYearBT50;
    


    @View (jello.ux.View)

    @View annotations can serves two purposes:

    1. Define a records list view with preset query parameters.
    2. Assign a custom records list view
      - Jello UX extension views prefixed with jello.
      - Custom view specified by absolute path to the view resource. See Custom views for more details.

    Examples:
    @View(name="cheapests", filter="price<20", top=10)
    @View(name="totalOrders", control="/demo/custom/chart/ChartView", select="name as label, totalSales as value")
    public class Product extends JelloEntity {
    
    @View(name="customMap", control="/demo/custom/mapView", expand="address", settings={"lat:address.lat", "lng:address.lng", "label:name", "marker:photo"})
    @View(name="jelloMap", control="jello.MapView", expand="address", settings={"lat:address.lat", "lng:address.lng", "label:name", "marker:photo"})
    @View(name="withAudit", audit=true)
    public class Supplier2 extends JelloEntity {
    

    Referring to entitie's view via OData is done with the following syntax

    ../jello/[data|view|meta]/namespace/entity::view-name

    Examples:
    http://localhost:8888/jello/view/demo.map/Supplier::jelloMap
    http://localhost:8888/jello/view/demo.catalog/Product::cheapests

    @Summary (jello.ux.Summary)

    Annotate an embedded field type with @Summary will hint the client how to render the field value in case only a summary is needed.


    Examples:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    @Summary("street + ',' + city + ' ' + zipCode + ',' + state")
    Address address;
    
    class Address extends JelloEntity {
       @Expose String street;
       @Expose String city;
       @Expose String state;
       @Expose String zipCode;
    }
    
    server side validation

    By default, Jello Views (JelloDataTable and JelloDataForm) will bind the data elements to the built-in Jello UX controls according to the element's type. Here is the list of built-in controls:

    InputCtrl, CheckboxCtrl, EnumSelector, TextareaCtrl, Reachtext, AttachmentCtrl, RefSelector, CollectionCtrl, AssociationCtrl, ComplexCtrl TreeSelector, RatingControl, DynamicCtrl.



    By default, Jello Views will bind the data elements to the built-in Jello UX controls according to the element's type. You can change this behavior by providing custom controls that implement the JelloControl JavaScript interface and then add @jello.ux.Control annotation to the element you want to bind the new control to.


    1. Write custom JS control

    First, you will need to provide a JavaScript control that implements the JelloControl interface. You can write this control from scratch or just wrap a 3rd party control with a JelloControl interface. Add the new control file to the war folder and make sure it is accessible via an HTTP request. The name of the js file should be the same as the name of the control class.


    JelloControl JavaScript interface
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // js file name should be the same as the name of the control name.
    // Control's constructor gets the parent container id, a settings object, and the field metadata.
    function controlName( containerId, settings, filedDef );
    		
    	// The render method gets a callback to be called once the control is ready and has been
    	// appended to the parent container. The method should empty the parent container before
    	// appending the control. The callback takes the newly created control object as its only argument.
    	render( onReadyCB );
    	
    	// Return the current value.
    	getValue( );
    	
    	// Set the control value.
    	setValue( value );
    	
    	// Bind an event listener function to be called on change event.  
    	// the following parameters should be passed to the listener function in this order:  
    	// the original triggered event, the control object, the current value.  
    	change( listener );
    		
    	// Make the control disabled or enabled. 
    	setDisabled( true|false );
    }
    

    2. Add @Control annotation

    @Control(src=controlFilePath[, settings={"propName1 : value1,...,"}]) (jello.ux.Control)

    Add this annotation to an element you wish to bind to a custom control. This annotation gets two input parameters:

    - src: relative path to the control js file (omit the .js suffix)

    - settings(optional): an array of strings in which each string contains the property's key and value in the format of "propName : value". JelloTableView makes use of the width property but with this parameter, you can pass any custom property to be handled by the custom control.


    Example:

    Consider the following example of Rating custom control. The control name is ratingControl and the file name will be ratingControl.js (refer to the Custom Control - case study to see complete code).

    custom control file
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    function ratingControl( containerId, settings, filedDef ) {
      this.container =  $('#' + containerId);
      this.settings = settings;
     
      this.render = function(onReady) {
         ...
          
         onReady(this);
      }
      
      this.getValue = function() {
        ...
      }
      
      this.setValue = function( value ) {
         ...
      }
      
      this.change = function(listener) {
        ...
      }
      
      this.setDisabled = function(state) {
        ...   
      }
    }
    

    Here is what the @Control annotation will look like:

    1
    2
    3
    	@Expose
    	@Control(src="/demo/custom/ratingControl", settings= {"width:150px"})
    	public Integer rating;
    

    And here is the view:

    custom control file

    Learn More:

    Check the demo and see to the complete Custom Control - case study.


    By default, Data Table view is used to display a records list. You can change this behavior by providing custom view control that implements the JelloViewControl JavaScript interface and then add @jello.ux.View annotation to the entity you want to bind the new view to.


    1. Write custom JS view control

    First, you will need to provide a JavaScript control that implements the JelloViewControl interface. You can write this control from scratch or just wrap a 3rd party control with a JelloViewControl interface. Add the new control file to the war folder and make sure it is accessible via HTTP request. The name of the js file should be the same as the name of the control class.


    JelloViewControl JavaScript interface
    1
    2
    3
    4
    5
    // js file name should be the same as the name of the control name.
    // Control's constructor get the parent container id, the view data, and a settings object.
    function ChartView( containerId, data, settings ) {
       // create custom view and append it to parent container.
    }
    

    2. Add @View annotation

    @View(view="view-name", src=controlFilePath[, settings={"propName1 : value1,...,"}]) (jello.ux.View)

    Add this annotation to an entity you wish to bind to a custom view.

    - src: relative path to the control js file (omit the .js suffix)

    - settings(optional): an array of strings in which each string contains the property's key and value in the format of "propName : value".

    See Custom map view control code sample.

    custom map view

    @UXAnnotation (jello.ux.UXAnnotation)

    In addition to the core jello.ux annotations, you can define custom annotations. Any custom annotation annotated with jello.ux.UXAnnotation will be exposed in the metadata document via REST call and therefore can be used to pass custom metadata to the client application.

    Example:
    - UX annotation
    package demo.ux;
    @Retention(RetentionPolicy.RUNTIME)  
    @Target({ElementType.FIELD })
    @UXAnnotation
    public @interface Link {
       public static final String Popup = "Popup";
       public static final String NavigateTo = "NavigateTo";
    
       String behavior() default Link.NavigateTo;
    }
    

    - Use in code
    @Link(behavior=Link.Popup)
    public String supplierSiteUrl;
    

    - Result in entity metadata
    {
       name: "supplierSiteUrl",
       demo.ux.Link: {
          behavior: "Popup"
       },
       type: "String"
    }
    


    Jello OData protocol is JSON based and includes comprehensive support for pagination, records count, data expands, and some unique features such as data preview and more. Thus, consuming these services by a custom front-end user interface becomes a straightforward task.


    Jello provides the following data view APIs:

    Required: //jello-framework.com/apis/v-1.2.8/assets/js/jelloDataView.min.js

    - $JELLO.getMetadata(entity, settings)

    - $JELLO.getMetadataAsync(entity, callback, settings)

    - $JELLO.getEntityListAsync(namespace, callback)

    - $JELLO.getNSListAsync(callback, expand)

    - jelloDataTable(containerId, entityMetadata, settings)

    - jelloDataForm(containerId, entityMetadata, settings)

    See Client API for more details.


    Reusable Jello modules

    Check the Jello Modules tutorial to learn how to create and consume Jello Modules.

    Last updated March 20, 2019.