JSON Forms goes Mobile with Ionic

December 21, 2018 | 4 min Read

The last couple of weeks we’ve been busy with completing an Ionic 3 based renderer set to JSON Forms. If you don’t know what Ionic is: Ionic is a cross-platform framework for building mobile apps. A new version, 4.x, currently in its beta and built on web components via Stencil, is available, while 3.x is considered stable and is built on Angular.

As we’ve added support bindings for Angular recently, which enable Angular-based renderer sets for JSON Forms, we’ve decided to add a renderer set for Ionic 3 as well. Transitioning to 4.x should be easy though, according to the migration guidelines of Ionic.

Feature set

The Ionic renderer set currently covers most concepts of JSON Forms, but not all of them. Here’s an quick overview:

Layouts

We cover Group (ion-card), VerticalLayout (ion-list), HorizontalLayout (ion-grid) and Categorization (ion-tabs).

Controls

All basic types are supported. For some of them we provide two renderers. In the latter case you can choose which one to pick by setting an `option` in the UI schema. Here’s a complete overview:

  • string (ion-input & ion-textarea)
  • number, integer (ion-input & ion-range)
  • dates (ion-datetime)
  • booleans (ion-toggle and ion-checkbox)
  • enums (ion-select & ionic-selectable)

We also provide a renderer for objects, such that controls can be bound against properties of type `object`.

Uncovered features

The Ionic renderer set currently does not support more advanced feature as, e.g. oneOf, anyOf, allOf. We provide an overview of covered features in our wiki.

Extending JSON Forms

One of the core principles of JSON Forms is customizability such that you can always plug-in your own renderers suited to your own needs, when necessary.

With the Ionic renderer set this is no different, so let’s look at an example.

Let’s suppose, for instance, that you want to replace the default number renderer with a rating control where you assign a rating between 1 and 5 to a property by clicking the respective number of stars.

A quick google search reveals that ionic3-star-rating seems to do what we are after. After installing it, we can start writing our custom control by extending

JsonFormsControl

from

@jsonforms/angular

 and using the rating component.

import { JsonFormsControl } from "@jsonforms/angular";
import { Component } from "@angular/core";
import { NgRedux } from "@angular-redux/store";
import { JsonFormsState } from "@jsonforms/core";

@Component({
  template: `
    <ionic3-star-rating
      activeIcon="ios-star"
      defaultIcon="ios-star-outline"
      activeColor="#488aff"
      defaultColor="#f4f4f4"
      readonly="false"
      [rating]="data"
    >
    </ionic3-star-rating>
  `,
  selector: "jsonforms-rating-control",

})
export class RatingControl extends JsonFormsControl {
  starRatingChange: Function
  constructor(ngRedux: NgRedux<JsonFormsState>, private events: Events) {
    super(ngRedux);
    this.starRatingChange = starRating => this.onChange({ value: starRating });
  }
    
  ngOnInit() {
    super.ngOnInit();
    this.events.subscribe('star-rating:changed', this.starRatingChange);
  }
  
  ngOnDestroy() {
    super.ngOnDestroy();
    this.events.unsubscribe('star-rating:changed', this.starRatingChange);
  }
}

The data property will be provided by

JsonFormsControl
``` for us and, as it name implies, it represents the currently available data. We also subscribe for 
```text
“star-rating:changed”

events in order to be notified whenever a change happens, so that we can update the data accordingly.

The only thing left to do is to register our

StarRatingControl

: We need to do so in the

declarations

and

entryComponents

sections of our app module and also register it with the store of JSON Forms. For the latter we can utilize JSON Forms’ Testers API that lets you formulate for which conditions the control should be considered applicable and if so, what priority it should have, e.g. a registration could look as follows:

renderers: [
  ...ionicRenderers,
  { renderer: RatingControl, tester: rankWith(5, and(isNumberControl, scopeEndsWith('rating)') }
]

In the example above with specify a priority of 5 if the control refers to a property of type number and its name is “rating”.

Give it a spin

If you like what you see and would like to play around with it a bit more, you can checkout our playground app on github, which demonstrates all features of the renderer set. We also provide instructions there on how to integrate the renderer set in one of your own projects.

Jonas, Maximilian & Philip

Jonas Helming, Maximilian Koegel and Philip Langer co-lead EclipseSource. They work as consultants and software engineers for building web-based and desktop-based tools. …