📺 "One project. One language. Three apps." Learn more in our upcoming code sharing webinar!

NativeScript Core

Building UI Plugins using Composite Components

When writing a plugin that shows some UI, you can take different paths. One of the easiest of them is to use existing {N} components as building blocks for a more complex UI component (composite), i.e. no explicit calls to native APIs. Thus you can even sometimes avoid using platform-specific files (like *.ios.ts, *.android.ts ...).

Bootstrap Your Plugin

First things first - you start off from a regular plugin. You can check the Building Plugins article for reference.

Add UI bits

Let's say you want to build a simple meme generator component with three properties, which you can use like:

    <ui:Meme imageSource="~/images/nativescript.png" topText="ROCK" bottomText="ROLL" />

...and when used in an app it looks like:

You can implement this by creating two files:

  • meme.ts: Contains properties, the implementation logic, and loads the UI.
  • meme.xml: Contains the UI and data bindings.

In meme.ts, you need to declare a class with the name of the UI element that will be used in the app:

export class Meme extends GridLayout {
    constructor() {
        super();

        let innerComponent = builder.load(__dirname + '/meme.xml') as View;
        innerComponent.bindingContext = this;

        this.addChild(innerComponent);
    }
}

As you see, in the constructor, we load the UI from the meme.xml and set its bindingContext to this, so that we can bind the XML to the properties:

<GridLayout rows="auto,*, auto"> 
    <Label row="0" text="" fontSize="64" textWrap="true" 
        horizontalAlignment="center" verticalAlignment="top"></Label>

    <Image rowSpan="3" src="" verticalAlignment="stretch"></Image>

    <Label row="2" text="" fontSize="64" textWrap="true" 
        horizontalAlignment="center" verticalAlignment="bottom"></Label>
</GridLayout>

The properties themselves are declared and registered in the .ts like:

export const topTextProperty = new Property<Meme, string>({ name: "topText", defaultValue: undefined });
export const bottomTextProperty = new Property<Meme, string>({ name: "bottomText", defaultValue: undefined });
export const imageSourceProperty = new Property<Meme, string>({ name: "imageSource", defaultValue: undefined });

...

imageSourceProperty.register(Meme);
topTextProperty.register(Meme);
bottomTextProperty.register(Meme);

For more details and the full source code of the described meme sample, check the NativeScript ui-plugin sample repo.

Make Your Plugin Angular-Compatible

Having your UI plugin developed successfully you could easily make it Angular-compatible following the steps described in Supporting Angular in UI Plugins article.