AngularJS Custom Directive for Expand Collapse

. 6 mins read

AngularJS Custom Directive for Expand Collapse

Tutorial on how to create an AngularJS custom Directive for expand and collapse with step by step instructions, demo and source code download.

Create the controller

Create a JS file demoController.js

// Creating the module
var demoApp = angular.module('demoApp', []);
// Creating the controller
demoApp.controller('DemoController', ['$scope', function($scope) {
}]);

Setup the controller to supply data

Initialize a scope variable ($scope.customDataList) with the data.

// Creating the module
var demoApp = angular.module('demoApp', []);
// Creating the controller
demoApp.controller('DemoController', ['$scope', function($scope) {
    $scope.customDataList = [{"id":"1", "itemTitle":"Sample Content 1", "itemDescription":"You can easily change the formatting of selected text in the document text by choosing a look for the selected text from the Quick Styles gallery on the Home tab. You can also format text directly by using the other controls on the Home tab. Most controls offer a choice of using the look from the current theme or using a format that you specify directly. To change the overall look of your document, choose new Theme elements on the Page Layout tab. To change the looks available in the Quick Style gallery, use the Change Current Quick Style Set command. Both the Themes gallery and the Quick Styles gallery provide reset commands so that you can always restore the look of your document to the original contained in your current template. Angular JS Custom Directive for expand or collapse. View more, view less implementation using angular Java Script"},
        {"id":"2", "itemTitle":"Sample Content 2", "itemDescription":"To change the overall look of your document, choose new Theme elements on the Page Layout tab. To change the looks available in the Quick Style gallery, use the Change Current Quick Style Set command."},
        {"id":"3", "itemTitle":"Sample Content 3", "itemDescription":"On the Insert tab, the galleries include items that are designed to coordinate with the overall look of your document. You can use these galleries to insert tables, headers, footers, lists, cover pages, and other document building blocks. When you create pictures, charts, or diagrams, they also coordinate with your current document look. You can easily change the formatting of selected text in the document text by choosing a look for the selected text from the Quick Styles gallery on the Home tab. You can also format text directly by using the other controls on the Home tab. Most controls offer a choice of using the look from the current theme or using a format that you specify directly. To change the overall look of your document, choose new Theme elements on the Page Layout tab. To change the looks available in the Quick Style gallery, use the Change Current Quick Style Set command. Both the Themes gallery and the Quick Styles gallery provide reset commands so that you can always restore the look of your document to the original contained in your current template. On the Insert tab, the galleries include items that are designed to coordinate with the overall look of your document. You can use these galleries to insert tables, headers, footers, lists, cover pages, and other document building blocks. When you create pictures, charts, or diagrams, they also coordinate with your current document look."}];
}]);

Create the template

Create a HTML file viewMoreDirective.html

<div class="cls-content">
  <div id="viewMoreDataDiv{{"{{customdata.id"}}}}" class="cls-description-content">
    <div style="background-color: #81bd00;color: white; border-radius:2px">
      <h3 style="padding: 5px; margin-left: 5px;">
        {{"{{customdata.itemTitle"}}}}
      </h3>
    </div>
    <span>
      {{"{{customdata.itemDescription"}}}}
    </span>
  </div>
  <div id="viewMoreDiv{{"{{customdata.id"}}}}" style="color: #81bd00;">
    <hr style="margin-bottom: 10px;" />
    <div id="viewMore{{"{{customdata.id"}}}}">
      <span class="vmbtn" align="center" ng-click="showMore(customdata.id)">View more</span>
    </div>
    <div id="viewLess{{"{{customdata.id"}}}}" hidden="hidden">
      <span class="vmbtn" align="center" ng-click="showLess(customdata.id)">View less</span>
    </div>
  </div>
</div>

Create the directive

Create a JS file viewMoreDirective.js

'use strict';
demoApp.directive('viewMore', function ($timeout, $window) {
  return {
    restrict: 'E',
        scope: {
          customdata: '='
        },
        templateUrl: 'directive/viewMoreDirective.html',                    
        link: function (scope, elm, attrs) {
          }
    };
});

viewMoreDirective.html has the template for the directive. customdata: '=' binds the data object having the content. In the viewMoreDirective.html, the content is accessed through customdata. For instance, customdata.id

Update the directive to handle window resize

The option to expand/ collapsed is displayed only if the content to be displayed exceeds the specified height of the content. Show/ hide of expand/ collapse option is handled in case of resizing the browser; in mobile devices, the view is shown accordingly.

'use strict';
demoApp.directive('viewMore', function ($timeout, $window) {
    return {
        restrict: 'E',
        scope: {
            customdata: '='
        },
        templateUrl: 'directive/viewMoreDirective.html',                    
        link: function (scope, elm, attrs) {
            var viewMore = function () {
                var id = scope.customdata.id;
                var offsetHeight = (elm[0].querySelector('#viewMoreDataDiv' + id)).offsetHeight; //Visible height of the viewMoreDataDiv div
                var scrollHeight = (elm[0].querySelector('#viewMoreDataDiv' + id)).scrollHeight; //Scroll height of the viewMoreDataDiv div
                
                if ((offsetHeight + 2) < scrollHeight) {
                    $("#viewMoreDiv" + id).show();
                } else {
                    $("#viewMoreDiv" + id).hide();
                }
            };
            $timeout(function () {
                viewMore();
                scope.$apply();
            }, 10);
            var w = angular.element($window);
            w.bind('resize', function () {
                updateView();
            });
            var updateView = function () {
                var id = scope.customdata.id;
                var $content = $('#viewMoreDataDiv' + id);
                $content.height('100px');
                $("#viewMore" + id).show();
                $("#viewLess" + id).hide();
                $timeout(viewMore, 0);
            }
        }
    };
});

Update the directive to handle View More / View Less button clicks

'use strict';
demoApp.directive('viewMore', function ($timeout, $window) {
    return {
        restrict: 'E',
        scope: {
            customdata: '='
        },
        templateUrl: 'directive/viewMoreDirective.html',                    
        link: function (scope, elm, attrs) {
            var viewMore = function () {
                var id = scope.customdata.id;
                var offsetHeight = (elm[0].querySelector('#viewMoreDataDiv' + id)).offsetHeight; //Visible height of the viewMoreDataDiv div
                var scrollHeight = (elm[0].querySelector('#viewMoreDataDiv' + id)).scrollHeight; //Scrollable height of the viewMoreDataDiv div
                
                if ((offsetHeight + 2) < scrollHeight) {
                    $("#viewMoreDiv" + id).show();
                } else {
                    $("#viewMoreDiv" + id).hide();
                }
            };
            $timeout(function () {
                viewMore();
                scope.$apply();
            }, 10);
            var w = angular.element($window);
            w.bind('resize', function () {
                updateView();
            });
            /** showMore - Called on click of 'View more' link **/
            scope.showMore = function (id) {
                var el = $("#viewMoreDataDiv" + id),
                curHeight = el.height(),
                autoHeight = el.css('height', 'auto').height(); //Temporarily change to auto and get the height.
                el.height(curHeight).animate({ height: autoHeight }, 600, function () {
                    /*Now, change the height to auto when animation finishes. 
                    Added to make the container flexible (Optional).*/
                    el.css('height', 'auto');
                });
                $("#viewMore" + id).hide();
                $("#viewLess" + id).show();
            }
            /** showLess - Called on click of 'View less' link **/
            scope.showLess = function (id) {
                $("#viewMoreDataDiv" + id).animate({ height: '100px' }, 500);
                $("#viewMore" + id).show();
                $("#viewLess" + id).hide();
            }
            var updateView = function () {
                var id = scope.customdata.id;
                var $content = $('#viewMoreDataDiv' + id);
                $content.height('100px');
                $("#viewMore" + id).show();
                $("#viewLess" + id).hide();
                $timeout(viewMore, 0);
            }
        }
    };
});

Include the directive markup in the view

To use the directive, add the directive mark-up in the HTML page. <view-more customdata="data"></view-more> This directive can also be used inside an ng-repeat.

<html data-ng-app="demoApp">
<head lang="en">
    <meta charset="UTF-8">
    <title>Angular JS custom directive to expand/collapse</title>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
    <script type="text/javascript"src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script type="text/javascript" src="controller/DemoController.js"></script>
    <script type="text/javascript" src="directive/viewMoreDirective.js"></script>
    <link type="text/css" rel="stylesheet" href="css/customStyles.css">
</head>
<body ng-controller="DemoController">
   <div>
        <div ng-repeat="data in customDataList" style="width: 95%;margin-top: 10px;">
            <view-more customdata="data"></view-more>
        </div>
    </div>
</body>
</html>

Demo and Download

Demo

Click here to view the demo in a new window.



Download Source Code

Download

RPA
Using Inject JS Script Activity in UiPath
02 Feb 2021

A comprehensive guide on how to use Inject JS Script Activity in UiPath.

RPA
Blue Prism Video Tutorial
03 Jul 2017

A well-structured video tutorial on Blue Prism, which could be the right starting point for your RPA career.