Step by Step Ruby on Rails

Ruby on Railsで実際にWebサイトを構築する手順をまとめています。

Bootstrap3のOffcanvasのJavaScriptをAngularJSで実行する方法

Bootstrap3のOffcanvasのサンプルをベースにレイアウトを作成しています。JavaScriptの機能をBootstrap3同梱のものからAngularJSに変更する手順をまとめました。

目次
(1)Turbolinksと一緒にAngularJSを使用する場合の注意点
(2)AngularJSの依存性のアノテーションの記述に注意
(3)折りたたみの機能をBootstrapの記述からAngularJSに変更
(4)"Toggle nav"の部分をAngularJSを使って変更


(1)Turbolinksと一緒にAngularJSを使用する場合の注意点

新しいページコンテンツをロードした後、AngularJSをアプリを再ブートストラップする必要があります。下記のようにモジュールの指定を変更します。
参考サイト
http://chrisltd.com/blog/2014/04/angularjs-rails4/

(AngularJSスクリプト)
var app = angular.module('myModule', []);

$(document).on('ready page:load', function(){
  angular.bootstrap(document.body, ['myModule']);
});

(ビュー)
<html ng-app="myModule">
 ↓
<html>

(2)AngularJSの依存性のアノテーションの記述に注意

production環境では、JavaScriptのminifiersによって関数のパラメータ名がリネームされてしまい、依存性のアノテーションの記述によっては動作しなくなります。

(問題のある例)
angular.module('myModule', ['ui.bootstrap'])

function CollapseDemoCtrl($scope) {
  $scope.isCollapsed = true;
}

(対策後)
myModule = angular.module('myModule', ['ui.bootstrap'])

function CollapseDemoCtrl($scope) {
  $scope.isCollapsed = true;
}
CollapseDemoCtrl.$inject = ['$scope'];
myModule.controller('CollapseDemoCtrl', CollapseDemoCtrl);

(3)折りたたみの機能をBootstrapの記述からAngularJSに変更

●変更部分

<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
 ↓
<button type="button" class="navbar-toggle" data-toggle="collapse" ng-click="isCollapsed = !isCollapsed">

<div class="navbar-collapse collapse">
 ↓
<div class="navbar-collapse" collapse="isCollapsed">

●Bootstrapの記述

<div class="navbar navbar-fixed-top navbar-inverse" role="navigation">
  <div class="container">
    <div class="navbar-header">
      <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">Project name</a>
    </div>
    <div class="collapse navbar-collapse">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">Home</a></li>
        <li><a href="#about">About</a></li>
        <li><a href="#contact">Contact</a></li>
      </ul>
    </div><!-- /.nav-collapse -->
  </div><!-- /.container -->
</div><!-- /.navbar -->


●AngularJSの記述に変更
(ビュー)
<div class="navbar navbar-fixed-top navbar-inverse" role="navigation">
  <div class="container">
    <div ng-controller="CollapseDemoCtrl">
      <div class="navbar-header">
        <button class="navbar-toggle" type="button" ng-click="isCollapsed = !isCollapsed">
          <span class="sr-only">Toggle navigation</span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" href="#">Project name</a>
      </div>
      <div class="navbar-collapse" collapse="isCollapsed">
        <ul class="nav navbar-nav">
          <li class="active"><a href="#">Home</a></li>
          <li><a href="#about">About</a></li>
          <li><a href="#contact">Contact</a></li>
        </ul>
      </div><!-- /.nav-collapse -->
    </div>
  </div><!-- /.container -->
</div><!-- /.navbar -->
</pre>

(スクリプト)
myModule = angular.module('myModule', ['ui.bootstrap'])

$(document).on('ready page:load', function(){
  angular.bootstrap(document.body, ['myModule']);
});

function CollapseDemoCtrl($scope) {
  $scope.isCollapsed = true;
}
CollapseDemoCtrl.$inject = ['$scope'];
myModule.controller('CollapseDemoCtrl', CollapseDemoCtrl);

(4)"Toggle nav"の部分をAngularJSを使って変更

ブラウザのウィンドウサイズが小さくなった場合に左右に画面を移動できる"Toggle nav"の部分は、Bootstrap3のOffcanvasのサンプルではjQueryを使って記述されています。ここでは、AngularJSのng-classを使って書換えています。

●ng-classディレクティブ

・HTML内でCSSクラスを動的にセットできます。

・下記サンプルコードでは、キーと値ペアのオブジェクトで指定していて、$scope.rowOffcanvasがtrueの場合は'row-offcanvas-right-active'CSSクラスがセットされ、右にスライドします。
ng-class="{'row-offcanvas-right-active': rowOffcanvas}"

●変更例
(HTML)
<div class="container" ng-controller="OffcanvasCtrl">
  <div class="row row-offcanvas row-offcanvas-right" ng-class="{'row-offcanvas-right-active': rowOffcanvas}">
    <div class="col-xs-12 col-sm-9">
      <p class="pull-right visible-xs">
        <button type="button" class="btn btn-primary btn-xs" ng-click="offcanvas()" tooltip-placement="bottom" tooltip="クリックすると左右にスライドし、隠れている部分を表示できます。">Toggle nav</button>
      </p>

(CSS)
.row-offcanvas-right-active {
    right: 50%; /* 6 columns */
  }

(AngularJS)
function OffcanvasCtrl($scope) {
  $scope.rowOffcanvas = false;
  $scope.offcanvas = function () {
    $scope.rowOffcanvas = !$scope.rowOffcanvas;
  };
}
OffcanvasCtrl.$inject = ['$scope'];
myModule.controller('OffcanvasCtrl', OffcanvasCtrl);