2014-09-28

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

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コントロールの定義
  2. UIコントロールメタデータの定義
  3. レンダラの実装
  4. 配布、利用
  5. まとめ

  6. Definition of UI controls

  7. Definition ofUI controls metadate
  8. Implementation of the renderer
  9. How to use
  10. Summary

こちらの公式ページの内容をもとに書いています。

Developing UI5 Controls in JavaScript

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 ""

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

    for item in items
      rm.write ""

      rm.renderControl item
      rm.write "
" rm.write ""

ある程度書き慣れてくると、レンダラについてはお決まりのパターンが見えてくるでしょう。また、似たような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を少しカスタムしたいケースだと思います。
その辺りは後編にて取り上げたいと思います。