Jonas Helming, Maximilian Koegel and Philip Langer co-lead EclipseSource, specializing in consulting and engineering innovative, customized tools and IDEs, with a strong …
JSON Forms goes Mobile with Ionic
December 21, 2018 | 4 min ReadThe 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.