sapui5openui5

[SAPUI5/OpenUI5]カスタムUIコントロールを作成する方法(前編)

September 28, 2014

8 min read

mitsuruogMitsuru Ogawa

How to create new own controls in OpenUI5(Part 1)

OpenUI5 は UI フレームワークという名前の通り、多くの優れた UI コントロールを持っていますが、場合によっては少しカスタムして使いたいという要望は時々あります。

さて、OpenUI5 にてカスタム UI コントロールを作成する方法は「新規で作成する」「既存の UI を拡張する」の 2 つありますが、少し長くなるので、2 部構成で説明していきます。 前編は新規で作成する方を説明します。

今回のデモはこちらで参照できます。

http://mitsuruog.github.io/sapui5-showroom/#/controls

目次

1. 新しい UI コントロールの定義(Definition of UI controls)

新しい UI コントロールを作成するためには、まずsap.ui.core.Controlを継承する必要があります。以下のコードは新規でmitsuruog.SayHelloという名前の UI コントロールを定義しています。

sap.ui.core.Control.extend "mitsuruog.SayHello",
  metadata: {}
  renderer: {}

2. UI コントロールメタデータの定義

新しく定義した UI コントロールが持つ特徴をメタデータ(定義情報)として定義していきます。定義できるメタデータの属性はPropertiesEventsAggregations(Associations)の 3 つです。順に説明していきます。

Properties

Properties とは、その名の通り UI コントロールに外部からアクセスできるプロパティ定義です。例えば、nameという Properties を定義した場合、UI コントロールを初期化(new)する際に、nameプロパティにパラメータを渡すことができます。以下の属性を定義します。

  • type: プロパティのデータタイプを指定します。これを指定する事で OpenUI5 が提供する validation が機能します。デフォルトはstringです。
  • defaultValue: デフォルトを指定します。何も指定しない場合はundefinedです。 Properties にはアクセスレベルが指定できるようです(未検証)。Object Metadata and Implementation

Events

UI コントロールから発火するカスタムイベント名を定義します。

Aggregations(Associations)

UI コントロールに外部からリストを渡したい場合に定義します。sap.m.Listitemssap.m.Pagecontentに相当します。以下の属性を定義します。

  • type: Aggregations に設定するクラスを定義します。sap.m.Listitems場合はsap.m.ListItemBaseです。デフォルトはsap.ui.core.controlです。
  • multiple: 0..nの場合はtrue0..1の場合はfalseにします。何も設定しない場合の挙動が面倒なので、必ず設定しましょう。
  • singularName: 単数の場合の名前を定義します。通常は複数系の「s」を取り除いた形を指定します。itemsの場合はitemです。この辺り、正直 OpenUI5 に慣れてないとピンとこないと思いますので、詳細は割愛します。

実装例)


sap.ui.core.Control.extend "mitsuruog.BlueContainer",

  metadata:
    properties:
      boxColor:
        type: "string"
        defaultValue: "#CBE6F3"
    events:
      hover: {}
    aggregations:
      items:
        type: "sap.ui.core.Control"
        multiple: true
        singularName: "item"

    renderer: {}

    onmouseover: (evt) ->
      @fireHover()

詳細は公式ベージを確認してください。

3. レンダラの実装

レンダラとは実際に UI コントロールの HTML を出力する部分です。HTML を書き出す際は、内部的にsap.ui.core.RenderManagerの各メソッドを呼び出します。良く使いそうなものはこちらです。

  • write: HTML を出力します
  • writeEscaped: エスケープして HTML を出力します
  • writeControlData: OpenUI5 上が内部で UI コントロールを管理するための ID を出力します。これが無い場合、内部のイベントがハンドルできません。結構重要です。
  • addStyle, writeStyles: インラインスタイルを出力します
  • addClass, writeClasses: CSS クラスを出力します
  • renderControl: 与えられた UI コントロールのレンダラを実行します。Aggregations(Associations)あたりで使うようです。

実装例)

sap.ui.core.Control.extend "mitsuruog.BlueContainer",

  metadata:
    # 省略

  renderer: (rm, control) ->

    rm.write "<div"
    rm.writeControlData control
    rm.addClass "blue"
    rm.writeClasses()
    rm.write ">"

    # Aggregations(Associations)のデータはこうやって受け取る
    items = control.getContent()

    for item in items
      rm.write "<div"
      rm.addStyle "display", "inline-block"
      rm.addStyle "border", "1px solid #{control.getBoxColor()}"
      rm.addStyle "margin", "7px"
      rm.addStyle "padding", "7px"
      rm.writeStyles()
      rm.write ">"

      rm.renderControl item
      rm.write "</div>"

    rm.write "</div>"

ある程度書き慣れてくると、レンダラについてはお決まりのパターンが見えてくるでしょう。また、似たような OpenUI5 のソースを読むのもいいと思います。 詳細は公式ページを参照してください。

JsDoc Report - SAP UI development Toolkit for HTML5 - API Reference - sap.ui.core.RenderManager

4. 配布、利用

配布方法は UI コントロールを 1 つの Javascript ファイルにまとめてindex.htmlで読み込めばいいと思います。 OpenUI5 にはRequireJSのようなモジュールシステムがあるので、以下のようにモジュール化して呼び出し先でロードします。

#
# カスタムUIコントロール側
#
jQuery.sap.declare "com.mitsuruog.sapui5.showroom.controls.BlueContainer"

sap.ui.core.Control.extend "mitsuruog.BlueContainer",

  # 以下、省略


#
# 呼び出し側
#
jQuery.sap.require "com.mitsuruog.sapui5.showroom.controls.BlueContainer"

sap.ui.jsview "someView",

  createContent: (oController) ->

    # new でUIコントロールを初期化します。
    blueContainer = new mitsuruog.BlueContainer

    # 以下、省略

5. まとめ

今回は新しい UI コンポーネントを作成する方法について説明しました。 実装の細かい部分は Github 上のサンプルを参照してください。

私が普段利用している OpenUI5 のモバイル用ライブラリ(sap.m〜)では v1.22 の時点で 73 の UI コントロールを持っています。OpenUI5 自体の UI が優れているため、新規で UI コントロールを作成するケースはあまりないように思えます。
また、レンダラを実装していると Java の taglib を思い出して、軽いめまいを覚えますね。(まぁそこは置いといて。)

経験的にも良くあるケースとしては、既存の UI を少しカスタムしたいケースだと思います。
その辺りは後編にて取り上げたいと思います。