Implementing Expandable and Collapsible Elements

In this example you will use custom AngularJS directives to build elements on the web page that can expand and contract. Each element will have a title and an expand/collapse button on top. When the collapse button is clicked, the contents of the element will be hidden. When the expand button is clicked, the contents will be shown again.

The purpose of this exercise is to solidify implementing custom AngularJS directives that nest inside each other and communicate with each other. In this example you also get to see how a scope gets isolated from the controller but shared between the expand container and the items in the container.

The folder structure for this example is as follows:

./server.js: Node.js web server that serves the static project files.

./images: Folder that contains the images used in the examples.

./ch11: Project folder.

./ch11/expand.html: AngularJS template for the project that implements the custom expandable directives.

./ch11/expand_list.html: AngularJS partial template for the expandable element directive.

./ch11/expand_item.html: AngularJS partial template for each individual item in the expandable element.

./ch11/js/expand.js: AngularJS application supporting the expandable element directives.

The code in Listing 11.10 contains the expand.js AngularJS application that defines the expandList and expandItem custom AngularJS directives. The transclude option is used to keep the contents that get defined in the template.

Note that in the expandList directive, the scope is an isolate but accepts the attributes title and exwidth, which are set to title and listWidth in the scope. Note that in line 27 the listWidth value is used to set the width of the style for items added to the expand list. Also listWidth is used in line 34 to set the css attribute width for the expandable list.

The expandItem directive requires the expandList directive to provide access to the addItem() function tin the expandList directive’s scope. Note that the myStyle attribute is used to build a style object that will be set to the ng-style for the item in the expanded list.

The way that expanding and collapsing work is that the myHide value is bound to each item in the expanded list using ng-hide in the template shown in Listing 11.11. The items property in the scope of expandList provides a list of scopes for each of the expandItem elements that get added. Then when the expand/collapse button is clicked, it is a simple matter of setting the myHide value to true or false in the scope for each item in the collapse() function to show or hide the items in the expanded element.

Listing 11.10 expand.js: AngularJS Application That Implements the expandList and expandItem Custom Directive to Provide Expandable and Collapsible Elements


01 angular.module('myApp', [])
02 .controller('myController', ['$scope', function($scope) {
03   $scope.items = [1,2,3,4,5];
04 }])
05 .directive('expandList', function() {
06   return {
07     restrict: 'E',
08     transclude: true,
09     scope: {title: '@', listWidth: '@exwidth'},
10     controller: function($scope) {
11       $scope.collapsed = false;
12       $scope.expandHandle = "-";
13       items = $scope.items = [];
14       $scope.collapse = function() {
15         if ($scope.collapsed){
16           $scope.collapsed = false;
17           $scope.expandHandle = "-";
18         } else {
19           $scope.collapsed = true;
20           $scope.expandHandle = "+";
21         }
22         angular.forEach($scope.items, function(item) {
23           item.myHide = $scope.collapsed;
24         });
25       };
26       this.addItem = function(item) {
27         item.myStyle.width = $scope.listWidth;
28         items.push(item);
29         item.myHide=false;
30       };
31     },
32     link: function(scope, element, attrs, expandCtrl) {
33       element.css("display", "inline-block");
34       element.css("width", scope.listWidth);
35     },
36     templateUrl: 'expand_list.html',
37   };
38 })
39 .directive('expandItem', function() {
40   return {
41     require: '^expandList',
42     restrict: 'E',
43     transclude: true,
44     scope: {},
45     controller: function($scope){
46         $scope.myHide = false;
47         $scope.myStyle = { width: "100px", "display": "inline-block" };
48       },
49     link: function(scope, element, attrs, expandCtrl) {
50       expandCtrl.addItem(scope);
51     },
52     templateUrl: 'expand_item.html',
53   };
54 });


Listing 11.11 contains the AngularJS partial template expand_list.html that provides the definition for the expandList element. The elements for the expand list header, including the expand/collapse button and the title, are added. The <div ng-transclude> element is where the expandItem elements will be placed.

Listing 11.11 expand_list.html: AngularJS Partial Template That Defines the expandList Element


01 <div>
02      <div class="expand-header">
03           <span class="expand-button"
04                 ng-click="collapse()">{{expandHandle}}</span>
05           {{title}}
06      </div>
07      <div ng-transclude></div>
08 </div>


Listing 11.12 contains the AngularJS partial template expand_item.html that provides the definition for the expandable items. Notice that ng-hide is set to myHide in the scope to expand/collapse the element. ng-style is set to myStyle so that we can set the width to the expand list width. The expand-item class enables us to easily change the item appearance using CSS. The ng-transclude is used to place the contents from the AngularJS template definition inside the list item.

Listing 11.12 expand_item.html: AngularJS Partial Template That Defines the expandItem Element


01 <div ng-hide="myHide"
02      ng-style="myStyle"
03      class="expand-item"
04      ng-transclude>
05 </div>


Listing 11.13 implements the AngularJS template that provides the styles for the page as well as definitions for the <expand-list> elements. Notice that four different <expand-list> elements are defined. The first is a simple list where the <expand-item> element contains just text. The next provides a single <expand-item> element with form elements. The third contains a mixture of different HTML elements in each <expand-item> element. The final one contains just an <img> element.

Note that each <expand-list> element contains a different value for the attributes title and exwidth, which results in lists with different titles and widths on the page. The results of the AngularJS application are shown in Figure 11.4. Notice the expanded and collapsed version of the elements.

Listing 11.13 expand.html: AngularJS Code That Styles and Implements Expandable/Collapsible Elements Using the expandList and expandItem Custom Directives


01 <!DOCTYPE html>
02 <html  ng-app="myApp">
03   <head>
04     <title>Expandable and Collapsible Lists</title>
05     <style>
06       * { vertical-align: top; }
07       expand-list{
08         border: 2px ridge black; }
09       .expand-header{
10         text-align: center;
11         font: bold 16px/24px arial;
12          background-image: linear-gradient(#CCCCCC, #EEEEEE);
13         }
14       .expand-button{
15         float: left; padding: 2px 4px;
16         font: bold 22px/16px courier;
17         color: white; background-color: black;
18         cursor: pointer;
19         border: 3px groove grey; }
20       .expand-item {
21         border: 1px ridge black;}
22       p { margin: 0px; padding: 2px;}
23       label { display: inline-block; width: 80px; padding: 2px; }
24       .small { width: 100px; padding: 2px; }
25       .large { width: 300px; }
26     </style>
27   </head>
28   <body>
29   <h2>Expandable and Collapsible Lists</h2>
30   <hr>
31   <div ng-controller="myController">
32     <expand-list title="Companion" exwidth="120px">
33       <expand-item>Rose</expand-item>
34       <expand-item>Donna</expand-item>
35       <expand-item>Martha</expand-item>
36       <expand-item>Amy</expand-item>
37       <expand-item>Rory</expand-item>
38     </expand-list>
39     <expand-list title="Form" exwidth="280px">
40       <expand-item>
41         <label>Name</label>
42         <input type="text" /><br>
43         <label>Phone</label>
44         <input type="text" /><br>
45         <label>Address</label>
46         <input type="text" /><br>
47         <label>Comment</label>
48         <textarea type="text"></textarea>
49       </expand-item>
50     </expand-list>
51     <hr>
52     <expand-list title="Mixed List" exwidth="300px">
53       <expand-item>Text Item</expand-item>
54       <expand-item><p>I think therefore I am.</p></expand-item>
55       <expand-item>
56         <img class="small" src="/images/jump.jpg" />Sunset
57       </expand-item>
58       <expand-item>
59         <ul>
60           <li>AngularJS</li>
61           <li>jQuery</li>
62           <li>JavaScript</li>
63         </ul>
64       </expand-item>
65     </expand-list>
66     <expand-list title="Image" exwidth="300px">
67       <expand-item>
68         <img class="large" src="/images/lake.jpg" />
69       </expand-item>
70     </expand-list>
71   </div>
72   </body>
73   <script src="http://code.angularjs.org/1.3.0/angular.min.js"></script>
74   <script src="js/expand.js"></script>
75 </html>


Image

Figure 11.4 Using custom AngularJS directives to build and implement expandable/collapsible web page elements.

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

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