Implementing Nested Directives

The final example illustrates how you can nest directives within each other and have them interact. Nesting directives is a great way to provide a parent context and container for custom elements that are related to each other. In this example the outer directive myPhotos acts as a container that can contain child directives named myPhoto.

Listing 7.5 implements two custom directives: myPhotos and myPhoto. The myPhotos directive is designed to be a container for the myPhoto directive. Notice that lines 7–18 define a controller that provides the functionality for the myPhotos directive, including an addPhoto() function. Because the code uses require:'^myPhotos' in the myPhoto directive, you can also call the addPhoto() method from the link() function by using the photosControl handle to the myPhotos controller.

Listing 7.6 implements the myPhotos and myPhoto directives in an AngularJS template. The myPhoto directives are nested inside the myPhotos directive. Notice that the title attribute is set on each myPhoto directive and linked to the scope in line 28 of Listing 7.5.

Listing 7.7 implements a partial template loaded by the myPhotos directive. It generates a <div> container and then uses the photos array in the myPhotos scope to build a list of links bound to the select() function, using ng-click. <div ng-transclude></div> provides the container for the myPhoto child elements.

Figure 7.3 shows the web page created by Listings 7.5, 7.6, and 7.7.

Listing 7.5 directive_custom_photos.js: Implementing Custom Directives That Interact with Each Other


01 angular.module('myApp', [])
02 .directive('myPhotos', function() {
03   return {
04     restrict: 'E',
05     transclude: true,
06     scope: {},
07     controller: function($scope) {
08       var photos = $scope.photos = [];
09       $scope.select = function(photo) {
10         angular.forEach(photos, function(photo) {
11           photo.selected = false;
12         });
13         photo.selected = true;
14       };
15       this.addPhoto = function(photo) {
16         photos.push(photo);
17       };
18     },
19     templateUrl: 'my_photos.html'
20   };
21 })
22 .directive('myPhoto', function() {
23   return {
24     require: '^myPhotos',
25     restrict: 'E',
26     transclude: true,
27     scope: { title: '@'},
28     link: function(scope, elem, attrs, photosControl) {
29       photosControl.addPhoto(scope);
30     },
31     template: '<div ng-show="selected" ng-transclude></div>'
32   };
33 });


Listing 7.6 directive_custom.html: An AngularJS Template That Implements Nested Custom Directives


01 <!doctype html>
02 <html ng-app="myApp">
03 <head>
04   <title>AngularJS Custom Directive</title>
05   <style>
06     img { width: 300px }
07   </style>
08 </head>
09 <body>
10   <h2>Custom Directive Photo Flip</h2>
11    <my-photos>
12      <my-photo title="Flower">
13        <img src="/images/flower.jpg"/>
14      </my-photo>
15      <my-photo title="Arch">
16        <img src="/images/arch.jpg"/>
17      </my-photo>
18      <my-photo title="Lake">
19        <img src="/images/lake.jpg"/>
20      </my-photo>
21      <my-photo title="Bison">
22        <img src="/images/bison.jpg"/>
23      </my-photo>
24    </my-photos>
25   <script src="http://code.angularjs.org/1.3.0/angular.min.js"></script>
26   <script src="js/directive_custom_photos.js"></script>
27 </body>
28 </html>


Listing 7.7 my_photos.html: A Partial AngularJS Template That Provides the Root Element for the myPhotos Custom Directive


01 <div>
02   <span ng-repeat="photo in photos"
03         ng-class="{active:photo.selected}">
04     <a href="" ng-click="select(photo)">{{photo.title}}</a>
05   </span>
06   <div ng-transclude></div>
07 </div>


Image

Figure 7.3 Implementing event directives in AngularJS template views.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset