DRYな備忘録

Don't Repeat Yourself.

AngularJSでBootstrapのModalを出す方法メモ

問題

  • AngularJSと、Bootstrapのui.bootstrap使ってて
  • BootstrapのModal機能とか使いたくなるけれど
  • Angular的なControllerや$scopeの扱いが混乱したのでメモ

参考

サンプル

親View。対応するControllerのメソッドをふつうに呼んでるだけ↓

<!-- モーダル開く親側のView -->
<ul>
  <li data-ng-repeat="task in tasks">
    <span>{{task.name}}</span><a href="#" data-ng-click="openDeleteConfirm(task)">さくじょ</a>
  </li>
</ul>

親Controller。もちろんopenDeleteConfirmをexportしてる。その中で、モーダルインスタンスを、各種パラメータ付きで生成してる。そのインスタンスからのコールバックはmodalInstance.result.then(funcOnClose, funcOnDismiss)で受け取れることがわかる↓

// モーダルを開く親側のController
angular.module('my.sample').controller("MyController",
  // ui.bootstrapを読んでいれば$modalが解決される
  function($scope, $modal) {
    $scope.openDeleteConfirm = function(task) {
      var modalInstance = $modal.open({
        templateUrl: "confirm-modal.html",//ファイルPATHでも可
        controller: "MyModalController",//モーダルに適用するコントローラを指定
        resolve: {//上記のコントローラで解決させたいDIのプロバイダ
          tasuku: function() {//あえての`tasuku`です
            return task;
          }
        }
      });
      // modalInstanceからのコールバックを受ける
      modalInstance.result.then(function() {
        window.alert("モーダル側Controllerでcloseが呼ばれた!");
      }, function() {
        window.alert("モーダル側Controllerでdismissが呼ばれた!");
      });
    };
  }
);

モーダル側のView。okやcancelという名前も、スコープは単にモーダル側のControllerに従ってるだけ。特にtaskToDeleteの部分がミソ↓

<script type="text/ng-template" id="confirm-modal.html">
  <div class="modal-header"><h3 class="modal-title">確認!</h3></div>
  <div class="modal-body">
    <p>「{{taskToDelete.name}}」を削除する?</p>
  </div>
  <div class="modal-footer">
    <!--この`ok`はモーダル側Controllerのokメソッドの意味-->
    <button class="btn btn-primary" ng-click="ok()">OK</button>
    <!--同様に、モーダル側Controllerのcancelメソッド-->
    <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
  </div>
</script>

モーダル側のController。親でopenされるときに渡されたresolveに従ってDIが解決できる。だからtasukuがここまで来れる。で、これをViewで参照したいので$scope.taskToDeleteに突っ込んでみた↓

angular.module('my.sample').controller('MyModalController',
  // $modalInstanceはデフォで解決される
  // 親コントローラで指定したtasukuもここで解決できる
  function($scope, $modalInstance, tasuku) {
    // ↑DI経由で渡してもらって、↓ここでViewの$scopeに突っ込む
    $scope.taskToDelete = tasuku;

    $scope.ok = function() {
      $modalInstance.close(tasuku.id);
    };
    $scope.cancel = function() {
      $modalInstance.dismiss(tasuku.id);
    };
    // このようにして親におけるmodalInstance.result.thenが呼ばれる
  }
);

f:id:otiai10:20141030000317p:plain

f:id:otiai10:20141030000451j:plain

DRYな備忘録

Angular2によるモダンWeb開発 TypeScriptを使った基本プログラミング

Angular2によるモダンWeb開発 TypeScriptを使った基本プログラミング