AngularJS : 1.6.5
Bootstrap : 3.3.7
※v1.2.3のサンプルはこちら。
■目次
(1)基本的なカスタムディレクティブの作成方法
(2)子スコープ、隔離スコープの設定
(3)transcludeオプション、ng-transcludeディレクティブの使用例
(4)ディレクティブ内でコントローラを生成し、他のディレクティブで利用
(5)compile関数の使用例
(1)基本的なカスタムディレクティブの作成方法
1)カスタムディレクティブを使用しない場合
- {{item.product_name}} : {{item.price | number:0}}円
2)カスタムディレクティブを使用した場合
1)カスタムディレクティブを使用しない場合 <ol> <li ng-repeat='item in products'> {{item.product_name}} : {{item.price | number:0}}円 </li> </ol> 2)カスタムディレクティブを使用した場合 <div products-list="products"></div>
var demoApp = angular.module('demoApp', []); demoApp.controller("cus1Ctrl", function($scope) { $scope.products = [ {product_name: "デジタルカメラ",price: 8500}, {product_name: "ノートパソコン",price: 39000}, {product_name: "テレビ",price: 15900}, {product_name: "ファンヒーター",price: 9800} ]; }); demoApp.directive("productsList", function () { return { link: function (scope, element, attrs) { scope.data = scope[attrs["productsList"]]; }, scope: true, template: "<ol><li ng-repeat='item in data'>{{item.product_name}} : {{item.price | number:0}}円</li></ol>", restrict: "A" } });
(2)子スコープ、隔離スコープの設定
0)親スコープと共有:商品リスト(カメラ、テレビ、パソコン)
①親スコープ
フィルター(変数name)
②カスタムディレクティブA
③カスタムディレクティブB
1)子スコープ:商品リスト(カメラ、テレビ、パソコン)
①親スコープ
フィルター(変数name)
②カスタムディレクティブA
③カスタムディレクティブB
2)隔離スコープ(2Way):商品リスト(カメラ、テレビ、パソコン)
①親スコープ
変数parebind
②カスタムディレクティブA
③カスタムディレクティブB
3)隔離スコープ(1Way):商品リスト(カメラ、テレビ、パソコン)
①親スコープ
変数parebind
②カスタムディレクティブA
③カスタムディレクティブB
4)隔離スコープ(親スコープの関数を実行)
①親スコープ
会員非会員
②カスタムディレクティブA
③カスタムディレクティブB
0)親スコープと共有:商品リスト(カメラ、テレビ、パソコン)<br /> <p> <strong>①親スコープ</strong><br /> <span>フィルター(変数name)<input ng-model=name /></span></br> </p> <strong>②カスタムディレクティブA</strong><br /> <div ordered-list0="products"></div> <strong>③カスタムディレクティブB</strong><br /> <div ordered-list0="products"></div> 1)子スコープ:商品リスト(カメラ、テレビ、パソコン)<br /> <p> <strong>①親スコープ</strong><br /> <span>フィルター(変数name)<input ng-model=name /></span></br> </p> <strong>②カスタムディレクティブA</strong><br /> <div ordered-list1="products"></div> <strong>③カスタムディレクティブB</strong><br /> <div ordered-list1="products"></div> 2)隔離スコープ(2Way):商品リスト(カメラ、テレビ、パソコン)<br /> <p> <strong>①親スコープ</strong><br /> <span>変数parebind<input ng-model="parebind" /></span></br> </p> <strong>②カスタムディレクティブA</strong><br /> <div ordered-list2 namescope="products" bindscope="parebind"></div> <strong>③カスタムディレクティブB</strong><br /> <div ordered-list2 namescope="products" bindscope="parebind"></div> 3)隔離スコープ(1Way):商品リスト(カメラ、テレビ、パソコン)<br /> <p> <strong>①親スコープ</strong><br /> <span>変数parebind<input ng-model="parebind" /></span></br> </p> <strong>②カスタムディレクティブA</strong><br /> <div ordered-list3 namescope={{products}} bindscope={{parebind}}></div> <strong>③カスタムディレクティブB</strong><br /> <div ordered-list3 namescope={{products}} bindscope={{parebind}}></div> 4)隔離スコープ(親スコープの関数を実行)<br /> <p> <strong>①親スコープ</strong><br /> <input type="radio" ng-model="group" value="member">会員<input type="radio" ng-model="group" value="">非会員<br/> </p> <strong>②カスタムディレクティブA</strong><br /> <div ordered-list4 namescope="products" bindscope="parebind" feescope="getFee(group)"></div> <strong>③カスタムディレクティブB</strong><br /> <div ordered-list4 namescope="products" bindscope="parebind" feescope="getFee(group)"></div>
var demoApp = angular.module('demoApp', []); demoApp.controller("scopeCtrl", function($scope) { $scope.products = [ {product_name: "デジタルカメラA",price: 8500}, {product_name: "ノートパソコンA",price: 39000}, {product_name: "テレビA",price: 15900}, {product_name: "デジタルカメラB",price: 9800}, {product_name: "テレビB",price: 25900} ]; $scope.name = "カメラ"; $scope.parebind = "親スコープで設定した初期値"; $scope.group = "member"; $scope.getFee = function (grp) { return grp == "member" ? "送料は無料です。" : "送料は1商品1,000円です。"; } }); demoApp.directive("orderedList0", function () { return { link: function (scope, element, attrs) { scope.data = scope[attrs["orderedList1"]]; }, scope: false, template: "<p>フィルター(変数name): <input ng-model=name /></p><ol><li ng-repeat='item in data | filter: name'>{{item.product_name}} : {{item.price | number:0}}円</li></ol></p>", restrict: "A" } }); demoApp.directive("orderedList1", function () { return { link: function (scope, element, attrs) { scope.data = scope[attrs["orderedList1"]]; }, scope: true, template: "<p>フィルター(変数name): <input ng-model=name /></p><ol><li ng-repeat='item in data | filter: name'>{{item.product_name}} : {{item.price | number:0}}円</li></ol></p>", restrict: "A" } }); demoApp.directive("orderedList2", function () { return { scope: { localname: "=namescope", localbind: "=bindscope" }, template: "<p>2Way(変数localbind): <input ng-model=localbind /><br />フィルター(変数key): <input ng-model=key /><ol><li ng-repeat='item in localname | filter: key'>{{item.product_name}} : {{item.price | number:0}}円</li></ol></p>", restrict: "A" } }); demoApp.directive("orderedList3", function () { return { scope: { localname: "@namescope", localbind: "@bindscope" }, template: "<p>1Way(変数localbind): <input ng-model=localbind /><br />データ(変数localname): {{localname}}</p>", restrict: "A" } }); demoApp.directive("orderedList4", function () { return { scope: { localname: "=namescope", localbind: "=bindscope", localfee: "&feescope" }, template: "<p><ol> <li ng-repeat='item in localname | filter: key'>{{item.product_name}} : {{item.price | number:0}}円</li></ol><span>※{{localfee()}}<span></p>", restrict: "A" } });
(3)transcludeオプション、ng-transcludeディレクティブの使用例
<input type="text" ng-model="title"><br/> <textarea ng-model="text" rows="3"></textarea><br/> <panel title="{{title}}">{{text}}</panel>
var demoApp = angular.module('demoApp', []); demoApp.controller("transCtrl", function($scope) { $scope.title = 'パネルのタイトル'; $scope.text = 'パネルの本文'; }); demoApp.directive("panel", function () { return { restrict: "E", scope: { title:'@' }, template: '<div class="panel panel-default"><div class="panel-heading"><h4>{{title}}</h4></div><div class="panel-body"><p ng-transclude></p></div></div>', transclude: true, } });
(4)ディレクティブ内でコントローラを生成し、他のディレクティブで利用
商品名 | 単価 | 個数 |
---|---|---|
合計金額(税込): | {{totalPrice | number:0}}円 |
<table class="table table-striped" product-total="totalPrice" product-data="products"> <tr><th>商品名</th><th>単価</th><th>個数</th></tr> <tr ng-repeat="item in products" product-item></tr> <tr><th>合計金額(税込):</th><td colspan="2">{{totalPrice | number:0}}円</td></tr> </table>
var demoApp = angular.module('demoApp', []); demoApp.controller("ctlCtrl", function($scope) { $scope.products = [ { name: "商品A", price: 100, quantity: 2 }, { name: "商品B", price: 150, quantity: 3 }, { name: "商品C", price: 200, quantity: 1 } ]; }); demoApp.directive("productItem", function () { return { template: "<td>{{item.name}}</td><td>{{item.price}}</td><td><input ng-model='item.quantity' /></td>", require: "^productTotal", link: function (scope, element, attrs, ctrl) { scope.$watch("item.quantity", function () { ctrl.updateTotal(); }); } } }); demoApp.directive("productTotal", function () { return { scope: { total: "=productTotal", data: "=productData" }, controller: function ($scope, $element, $attrs) { this.updateTotal = function() { var calc = 0; for (var i = 0; i < $scope.data.length; i++) { calc += $scope.data[i].quantity * $scope.data[i].price * 1.08; } $scope.total = calc; } } } });
(5)compile関数の使用例
パネルタイトル
<panel-repeat repeat="3"> <div class="panel panel-default"> <div class="panel-heading"> <h2 class="panel-title">パネルタイトル</h3> </div> <div class="panel-body"> パネル本文。タイトルをクリックすると色が変ります。 </div> </div> </panel-repeat>
var demoApp = angular.module('demoApp', []); demoApp.directive("panelRepeat", function () { return { restrict: "E", compile: function(tElement, attrs) { var content = tElement.children(); for (var i = 1; i < attrs.repeat; i++) { tElement.append(content.clone()); }; return function (scope, elem, attrs) { elem.on('click', function() { elem.find("h2").css({ "color": "red" }); }); }; } }; });