As our application grows, we need to consider the possibility of splitting it into different modules. It comes with it a lot of advantages, thus helping us to find the best way to test and evolve each module separately from the others and also to share each module with other projects.
In this Lesson, we are going to cover the following topics:
By gaining an in-depth understanding of the underlying business inside our application, we can isolate each group of functionalities (which are correlated) into a separated module. In the case of our parking application, we can split it into three different modules:
First, we need to create each new module separately and then they need to be declared inside the parking application module such that they are available.
The UI module will contain the directives that we created in Lesson 2, Creating Reusable Components with Directives.
To create an isolated and easy-to-use module, we should consider placing the entire code inside a unique file.
For now, let's start by creating our new module called ui
in the app.js
file, as follows:
var ui = angular.module("ui", []);
After that, we will declare each component separated in its own file. This will improve the maintainability of the module, facilitating the access to the components. The template is another aspect that we need to take care. In Lesson 2, Creating Reusable Components with Directives, we separated it from the directive's code. However, though we want to deliver this library in an easier format, it would be a good choice to embed its code within the component.
There are plugins for Grunt, such as grunt-html-to-js
that may perform this tough and boring job for us. Consider the following code snippet in the alertDirective.js
file:
ui.directive("alert", function () { return { restrict: 'E', scope: { topic: '@' }, replace: true, transclude: true, template: "<div class='alert'>" + "<span class='alert-topic'>" + "{{topic}}" + "</span>" + "<span class='alert-description' ng-transclude>" + "</span>" + "</div>" }; });
Consider the following code snippet in the accordionDirective.js
file:
ui.directive("accordion", function () { return { restrict: "E", transclude: true, controller: function ($scope, $element, $attrs, $transclude) { var accordionItens = []; var addAccordionItem = function (accordionScope) { accordionItens.push(accordionScope); }; var closeAll = function () { angular.forEach(accordionItens, function (accordionScope) { accordionScope.active = false; }); }; return { addAccordionItem: addAccordionItem, closeAll: closeAll }; }, template: "<div ng-transclude></div>" }; }); ui.directive("accordionItem", function () { return { restrict: "E", scope: { title: "@" }, transclude: true, require: "^accordion", link: function (scope, element, attrs, ctrl, transcludeFn) { ctrl.addAccordionItem(scope); element.bind("click", function () { ctrl.closeAll(); scope.$apply(function () { scope.active = !scope.active; }); }); }, template: "<div class='accordion-item'>" + "{{title}}" + "</div>" + "<div " + "ng-show='active' " + "class='accordion-description' " + "ng-transclude" + ">" + "</div>" }; });
Great! Now we are ready to pack our library inside one script file. For this, again, we may rely on Grunt, through the grunt-contrib-concat
plugin, for creating this concatenation for us. The destination file in this case would be ui.js
, and we are going to declare it inside the index.html
file of our parking application.
The search module will contain carSearchService
, which we created in Lesson 4, Dependency Injection and Services.
Again, we are going to start by declaring the module search in the app.js
file, as follows:
var search = angular.module("search", []);
Because we want to deliver this service as a reusable component, it would be nice to get rid of the car concept, making it more generic. To do that, let's just change it from car to entity. Consider the following code snippet in the searchService.js
file:
search.factory('searchService', function ($timeout, $q) { var _filter = function (entities, criteria) { var deferred = $q.defer(); $timeout(function () { var result = []; angular.forEach(entities, function (entity) { if (_matches(entity, criteria)) { result.push(entity); } }); if (result.length > 0) { deferred.resolve(result); } else { deferred.reject("No results were found!"); } }, 1000); return deferred.promise; }; var _matches = function (entity, criteria) { return angular.toJson(entity).indexOf(criteria) > 0; }; return { filter: _filter } });
Now that our search
module is ready, we can use it with any project we want! The name of this script, after the files, concatenation, will be search.js
, and we need to import it to the index.html
file.
It's time to create our application module and declare our new modules ui
and search
as our dependencies. Also, we need to include the ngRoute
and ngAnimate
modules in order to to enable the routing and animation mechanisms. Consider the following code snippet in the app.js
file:
var parking = angular.module("parking", ["ngRoute", "ngAnimate", "ui", "search"]);
That's it! Now, we just need to import the scripts inside our index.html
file, as follows:
<!doctype html> <html ng-app="parking"> <head> <title>[Packt] Parking</title> <!-- Application CSS --> <link rel="stylesheet" type="text/css" href="css/app.css"> <!-- Application Libraries --> <script src="lib/angular.js"></script> <script src="lib/angular-route.js"></script> <script src="lib/angular-animate.js"></script> <script src="lib/ui.js"></script> <script src="lib/search.js"></script> <!-- Application Scritps --> <script src="js/app.js"></script> <script src="js/constants.js"></script> <script src="js/controllers.js"></script> <script src="js/filters.js"></script> <script src="js/services.js"></script> <script src="js/config.js"></script> <script src="js/run.js"></script> </head> <body> <div ng-view></div> </body> </html>
A major part of the applications has concepts, which we could think of developing as a separated module. Beyond this, it is an excellent opportunity to contribute by opening the source code and evolving it with the community!
AngularJS has a huge community and thousands of modules available for use. There are lots of things that we actually don't need to worry about while developing something by ourselves! From tons of UI components to the integration with many of the most well-known JavaScript libraries such as Highcharts, Google Maps and Analytics, Bootstrap, Foundation, Facebook, and many others, you may find more than 500 modules on the Angular Modules website, at www.ngmodules.org.
3.145.11.182