LoginSignup
0

More than 5 years have passed since last update.

Office UI Fabricのラジオボタンとドロップダウンリスト

Last updated at Posted at 2015-12-06

今回はOffice UI Fabtic(以下"OfficeUI")のラジオボタンとドロップダウンリストについて解説します。どちらも複数の項目から一項目選択するためのUIなので、本記事でまとめて説明しようと思います。

ラジオボタン

まずはラジオボタンです。表示例は以下になります。
(選択項目はあいまいみーから引用しています)

img100.png

上記の表示例のサンプルコードは以下になります。

「ms-ChoiceFieldGroup」クラスでラジオボタンの選択項目をグルーピングして、「ms-ChoiceField」クラスの中に「ms-ChoiceField-input」を指定したラジオボタンそのものと、付随するラベルを記述する形になります。ms-ChoiceFieldクラスを指定したDIV要素がラジオボタンの一項目になるので、この要素を列挙することでラジオボタン(選択項目)が増やせます。

<!DOCTYPE html>
<html ng-app="App">
  <head>
    <meta charset="utf-8" />
    <title>Radio Button Sample</title>
    <link rel="stylesheet" href="//appsforoffice.microsoft.com/fabric/1.0/fabric.min.css">
    <link rel="stylesheet" href="//appsforoffice.microsoft.com/fabric/1.0/fabric.components.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
    <style>
      .my-sample { border: thin solid; border-radius: 4px; padding: 4px; margin-top: 10px; }
      .my-bold   { color: #e4007f; }
    </style>
  </head>
  <body ng-controller="AppController">
    <div class="ms-Grid"> <!-- ラジオボタンの選択内容で表示を変える -->
      <div class="ms-Grid-row">
        <div class="ms-Grid-col ms-u-sm6 ms-u-md8 ms-u-lg12">
          ぽのか先輩は&nbsp;<b class="my-bold">{{radioLabel}}</b>&nbsp;です。
        </div>
      </div>
    </div>
    <div class="ms-Grid"> <!-- ラジオボタンを表示する -->
      <div class="ms-Grid-row">
        <div class="ms-Grid-col ms-u-sm3 ms-u-md4 ms-u-lg6 my-sample">
          <div class="ms-ChoiceFieldGroup" ng-repeat="radio in radioButtons">
            <div class="ms-ChoiceField">
              <input id="radio{{radio.id}}" class="ms-ChoiceField-input" type="radio" name="ponokaName"
                     ng-model="ponokaName" ng-value="radio.value" ng-click="choiceRadioLabel(radio)">
              <label for="radio{{radio.id}}" class="ms-ChoiceField-field">
                <span class="ms-Label">{{radio.label}}</span>
              </label>
            </div>
          </div>
        </div>
      </div>
    </div>
    <script>
      var app = angular.module('App', []);
      app.controller('AppController', ['$scope',
        function($scope) {
          $scope.init = function() {
            $scope.radioButtons = [
              { id: 0, label: "自販機釣り銭パカパカ二郎総帥", value: 0 },
              { id: 1, label: "ポツダム宣言大好き太郎先輩",   value: 1 },
              { id: 2, label: "第三次声優ブームオタク",       value: 2 },
            ];
            $scope.choiceRadioLabel($scope.radioButtons[0]);
          }
          $scope.choiceRadioLabel = function(radio) {
            $scope.radioLabel = radio.label;
          }
          $scope.init();
        }
      ]);
    </script>
  </body>
</html>

ちなみに、単にms-ChoiceFieldを列挙する形でラジオボタンの選択項目を作成すると、先の表示例のように各項目が縦に配置されます。選択項目を横に並べて配置する場合は、グリッド配置を使用するなど、一手間必要になります。参考までに、以下は横に配置した場合の表示例です。
(グリッド配置については明日の記事で解説する予定です)

img101.png

先のサンプルコードにおけるラジオボタン表示部分を以下の内容で置き換えると、選択項目が横配置になります。

    <div class="ms-Grid"> <!-- ラジオボタンを表示する -->
      <div class="ms-Grid-row">
        <div class="ms-Grid-col ms-u-lg12 my-sample">
          <div class="ms-ChoiceFieldGroup" ng-repeat="radio in radioButtons">
            <div class="ms-Grid-col ms-u-sm4 ms-u-md4 ms-u-lg4">
              <div class="ms-ChoiceField">
                <input id="radio{{radio.id}}" class="ms-ChoiceField-input" type="radio" name="ponokaName"
                       ng-model="ponokaName" ng-value="radio.value" ng-click="choiceRadioLabel(radio)">
                <label for="radio{{radio.id}}" class="ms-ChoiceField-field">
                  <span class="ms-Label">{{radio.label}}</span>
                </label>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

ドロップダウンリスト

続いてドロップダウンリストです。表示例は以下のようになります。

img103.png

上記のサンプルコードは以下になります。が、現状(2015年12月6日時点)のドロップダウンリストは、開発者側から見るとちょっと使いにくい……、というのが正直な感想です。

<!DOCTYPE html>
<html ng-app="App">
  <head>
    <meta charset="utf-8" />
    <title>Dropdown List Sample</title>
    <link rel="stylesheet" href="//appsforoffice.microsoft.com/fabric/1.0/fabric.min.css">
    <link rel="stylesheet" href="//appsforoffice.microsoft.com/fabric/1.0/fabric.components.min.css">
    <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
    <script type="text/javascript" src="https://rawgit.com/furandon-pig/b00192562399e16b8c0b/raw/ab78c58452ee94b8d66ee3798773a6d6e32093ef/officeui_dropdown_helper.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
    <script type="text/javascript">
      var ddd = null;
      $(document).ready(function() {
        if ($.fn.Dropdown) {
          ddd = $('.ms-Dropdown').Dropdown();
        }
        if(fabric && fabric['Dropdown']) {
          var component, componentHolder;
          componentHolder = document.querySelector('.component-holder');

          if (componentHolder) {
            component = new fabric.Spinner(componentHolder);
          }
        }
      });
    </script>
  </head>
  <body ng-controller="AppController">
    <div class="ms-Grid"> <!-- ラジオボタンを表示する -->
      <div class="ms-Grid-row">
        <div class="ms-Grid-col ms-u-sm6 ms-u-md8 ms-u-lg12">
          <div class="ms-Grid-col ms-u-sm2 ms-u-md2 ms-u-lg2">ぽのか先輩は&nbsp;</div>
          <div class="ms-Grid-col ms-u-sm4 ms-u-md4 ms-u-lg4">
            <div class="ms-Dropdown" tabindex="0">
              <select class="ms-Dropdown-select" ng-repeat="list in lists">
                <option class="ms-Dropwodn-item" checked value="{{list.value}}">
                  {{list.label}}
                  <i class="ms-Icon ms-Icon--caretDown"></i>
                </option>
              </select>
            </div>
          </div>
          <div class="ms-Grid-col ms-u-sm2 ms-u-md2 ms-u-lg2">&nbsp;です。</div>
        </div>
      </div>
    </div>
    <script>
      var app = angular.module('App', []);
      app.controller('AppController', ['$scope',
        function($scope) {
          $scope.init = function() {
            $scope.lists = [
              { id: 0, label: "自販機釣り銭パカパカ二郎総帥", value: 0, },
              { id: 1, label: "ポツダム宣言大好き太郎先輩",   value: 1, },
              { id: 2, label: "第三次声優ブームオタク",       value: 2, },
            ];
          }
          $scope.init();
        }
      ]);
    </script>
  </body>
</html>

OfficeUIドロップダウンリストの(バッド)ノウハウ

ドロップダウンの初期化

ボタン、テキストボックス等、これまで紹介したきたOfficeUIのコンポーネントはHTMLタグとクラスを指定するだけでそのまま使用できていたのですが、ドロップダウンリストはSELECTタグの値をOfficeUI側でコピーし、独自のポップアップメニューを表示するという実装のため、Webページの読み込み時にOfficeUI用のドロップダウンリストUIの初期化が必要となっています。

具体的には、先のドロップダウンリストのサンプルコードにおける、以下の部分で初期化を行っています。
(実はこのあたりのOfficeUIのGUI初期化処理はよく把握できていません……)

    <script type="text/javascript">
      var ddd = null;
      $(document).ready(function() {
        if ($.fn.Dropdown) {
          ddd = $('.ms-Dropdown').Dropdown();
        }
        if(fabric && fabric['Dropdown']) {
          var component, componentHolder;
          componentHolder = document.querySelector('.component-holder');

          if (componentHolder) {
            component = new fabric.Spinner(componentHolder);
          }
        }
      });
    </script>

さらに、上記コード中の「$('.ms-Dropdown').Dropdown();」はOffice Dev Center - Fabric Home PageDropdownサンプルをみると外部のJavaScriptコードを参照する形になっています(単一のHTMLに入れるにはちょっとJavaScriptの行数が多い)。

そのため、本サンプルでも外部JavaScriptとしてGistに置いたスクリプトを読み込む形になっています。

加えて、ドロップダウンメニューに「▼」(ms-Icon--caretDownアイコン)を表示させるため、以下の修正を加えています。
(MSのサンプルページでは▼が表示されているのだけれど……)

--- officeui_dropdown_helper.js 2015-12-06 19:08:53.504426520 +0900
+++ officeui_dropdown_helper.js 2015-12-06 19:02:26.570557696 +0900
@@ -1,4 +1,13 @@
-                  
+/*
+ * Office UI Fabric Advent Calendar 2015用のドロップダウンボックスの
+ * サンプルプログラムで使用しているヘルパスクリプト
+ *
+ * 以下のサンプルプログラム(MIT License)のJSコードをサンプル用に一部
+ * 修正しています。
+ *   Dropdown
+ *   http://dev.office.com/fabric/components/dropdown
+ */
+
 // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE in the project root for license information.

 /**
@@ -139,7 +148,9 @@
                     $(this).addClass('is-selected');

                     /** Update the replacement dropdown's title. */
-                    $(this).parents().siblings('.ms-Dropdown-title').html($(this).text());
+                    $(this).parents().siblings('.ms-Dropdown-title').html($(this).text()
+                        + '<i class="ms-Icon ms-Icon--caretDown" aria-hidden="true"></i>');
+                    $(this).parents().siblings('.ms-Dropdown-title').css('vertical-align', 'middle');

                     /** Update the original dropdown. */
                     var selectedItemText = $(this).text();

AngularJSでドロップダウン項目にng-model,ng-clickを指定したい

さらにちょっと困る点として、HTMLに記載したSELECTからOfficeUI独自のドロップダウンリスト表示のため、内部用にSELECT項目のデータ(DOM)を作成するような動作になっています。

これはAngularJSを組みわせて使用する場合、「どうやってOfficeUIが作成したDOMにng-XXを設定するか」という問題が発生します。

以前筆者が作成したOfficeUIのGUI部品サンプルプログラムでは、若干無理矢理な感じで対応していました。この辺りについても、後日Advent Calendarでご紹介できればと思います。

選択項目の追加はどうするの?問題

もう一つ、Webページ読み込み時にSELECT項目からOfficeUI用のSELECTデータを作成しているため、「後からSELECT項目を追加したい場合はどうするの?」問題があります。これも対応できないわけではありませんが、ちょっとバッドノウハウ感漂う方法になります。

というわけで、OfficeUIのドロップダウンリストについては、もうちょっとノウハウの溜め込みが必要そうです。

まとめ

今日はOfficeUIのラジオボタンとドロップダウンリストについて解説しました。これで基本的なUIコンポーネントについては一通り紹介できたことになります。

明日はUIコンポーネントから少し離れて、レスポンシブルレスポンシブグリッドまわりの話をしたいと思います。

参考URL

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0