AngularJS - Essentials

[Packt] Parking

[ 11 ] Getting Started with AngularJS
Plate
{{car.plate}}
Apart from learning how to set up the framework in this section, we also introduced some directives that we are going to study in the Chapter 2, Creating Reusable Components with Directives. The ngController directive is used to bind the parkingCtrl controller to the view, whereas the ngRepeat directive iterates over the car's array. Also, we employed expressions such as {{car.plate}} to display the plate of the car. Finally, to add new cars, we applied the ngModel directive, which creates a new object called car with the plate property, passing it as a parameter of the park function, called through the ngClick directive. To improve the loading page's performance, you are recommended to use the minified and obfuscated version of the script that can be identified by angular.min. js. Both minified and regular distributions of the framework can be found on the official site of AngularJS (http://www.angularjs.org) or in the Google Content Delivery Network (CDN). Organizing the code As soon as we start coding our views, controllers, services, and other pieces of the application, as it used to happen in the past with many other languages and frameworks, one question will certainly come up: "how do we organize the code?" Most software developers struggle to decide on a lot of factors. This includes figuring out which is the best approach to follow (not only regarding the directory layout, but also about the file in which each script should be placed), whether it is a good idea to break up the application into separated modules, and so on. [ 12 ] Chapter 1 This is a tough decision and there are many different ways to decide on these factors, but in most cases, it will depend simply on the purpose and the size of the application. For the time being, our challenge is to define an initial strategy that allows the team to evolve and enhance the architecture alongside application development. The answers related to deciding on the factors will certainly keep coming up as time goes on, but we should be able to perform some refactoring activities to keep the architecture healthy and up to date. Four ways to organize the code There are many ways, tendencies, and techniques to organize the project's code within files and directories. However, it would be impossible to describe all of them in detail, and we will present the most used and discussed styles in the JavaScript community. Throughout the book, we will apply each of the following styles to our project as far as it evolves. The inline style Imagine that you need to develop a fast and disposable application prototype. The purpose of the project is just to make a presentation or to evaluate a potential product idea. The only project structure that we may need is the old and good index.html file with inline declarations for the scripts and style: app/ -> files of the application index.html -> main html file angular.js -> AngularJS script If the application is accepted, based on the prototype evaluation, and becomes a new project, it is highly recommended that you create a whole structure from scratch based on one of the following styles. The stereotyped style This approach is appropriate for small apps with a limited number of components such as controllers, services, directives, and filters. In this situation, creating a single file for each script may be a waste. Thus, it could be interesting to keep all the components in the same file in a stereotyped way as shown in the following code: app/ -> files of the application css/ -> css files app.css -> default stylesheet js/ -> javascript application components [ 13 ] Getting Started with AngularJS app.js -> main application script controllers.js -> all controllers script directives.js -> all directives script filters.js -> all filters script services.js -> all services script lib/ -> javascript libraries angular.js -> AngularJS script partials/ -> partial view directory login.html -> login view parking.html -> parking view car.html -> car view index.html -> main html file With the application growing, the team may choose to break up some files by shifting to the specific style step by step. The specific style Keeping a lot of code inside the same file is really hard to maintain. When the application reaches a certain size, the best choice might be to start splitting the scripts into specific ones as soon as possible. Otherwise, we may have a lot of unnecessary and boring tasks in the future. The code is as follows: app/ -> files of the application css/ -> css files app.css -> default stylesheet js/ -> javascript application components controllers/ -> controllers directory loginCtrl.js -> login controller parkingCtrl.js -> parking controller carCtrl.js -> car controller directives/ -> directives directory filters/ -> filters directory services/ -> services directory app.js -> main application script lib/ -> javascript libraries angular.js -> AngularJS script partials/ -> partial view directory login.html -> login view parking.html -> parking view car.html -> car view index.html -> main html file [ 14 ] Chapter 1 In this approach, if the number of files in each directory becomes oversized, it is better to start thinking about adopting another strategy, such as the domain style. The domain style With a complex domain model and hundreds of components, an enterprise application can easily become a mess if certain concerns are overlooked. One of the best ways to organize the code in this situation is by distributing each component in a domain-named folder structure. The code is as follows: app/ -> files of the application application/ -> application module directory app.css -> main application stylesheet app.js -> main application script login/ -> login module directory login.css -> login stylesheet loginCtrl.js -> login controller login.html -> login view parking/ -> parking module directory parking.css -> parking stylesheet parkingCtrl.js -> parking controller parking.html -> parking view car/ -> car module directory car.css -> car stylesheet carCtrl.js -> car controller car.html -> car view lib/ -> javascript libraries angular.js -> AngularJS script index.html -> main html file Summary Since the creation of the Web, many technologies related to the use of HTML and JavaScript have evolved. These days, there are lots of great frameworks such as AngularJS that allow us to create really well-designed web applications. In this chapter, you were introduced to AngularJS in order to understand its purposes. Also, we created our first application and took a look at how to organize the code. In the next chapter, you will understand how the AngularJS directives can be used and created to promote reuse and agility in your applications. [ 15 ] Creating Reusable Components with Directives The Document Object Model (DOM) is a convention created by W3C in 1998 for documents written in HTML, XHTML, and XML in an object tree, which is used by the browsers throughout the rendering process. By means of the DOM API, it is possible to traverse the hierarchical structure of the tree to access and manipulate information. Every time we access a web page, the browser sends a request to the server and then waits for the response. Once the content of the HTML document is received, the browser starts the analysis and the parse process in order to build the DOM tree. When the tree building is done, the AngularJS compiler comes in and starts to go through it, looking into the elements for special kinds of attributes known as directives. Creating Reusable Components with Directives The following diagram describes the bootstrapping process of the framework that is performed during the compilation process: HTML Browser AngularJS $compile Dynamic $compile DOM (dom) (view) ($rootScope) Source: Official documentation (www.angularjs.org) This chapter will present everything about directives, which is one of the most important features of AngularJS. Also, we will create our own directives step by step. The following are the topics that we'll be covering in this chapter: • What is a directive? • Using built-in directives of AngularJS • Refactoring application organization • Creating our own directives • Animation What is a directive? A directive is an extension of the HTML vocabulary that allows us to create new behaviors. This technology lets the developers create reusable components that can be used within the whole application and even provide their own custom components. [ 18 ] Static DOM ng-app="module" $injector $rootScope DOM Content Loaded Event Chapter 2 The directive can be applied as an attribute, element, class, and even as a comment, using the camelCase syntax. However, because HTML is case insensitive, we can use a lowercase form. For the ngModel directive, we can use ng-model, ng:model, ng_model, data-ng-model, and x-ng-model in the HTML markup. Using AngularJS built-in directives By default, a framework brings with it a basic set of directives such as iterate over an array, execute a custom behavior when an element is clicked, or even show a given element based on a conditional expression, and many others. The ngApp directive The ngApp directive is the first directive we need to understand because it defines the root of an AngularJS application. Applied to one of the elements, in general HTML or body, this directive is used to bootstrap the framework. We can use it without any parameter, thereby indicating that the application will be bootstrapped in the automatic mode, as shown in the following code: index.html [Packt] Parking However, it is recommended that you provide a module name, defining the entry point of the application in which other components such as controllers, services, filters, and directives can be bound, as shown in the following code: index.html [Packt] Parking [ 19 ] Creating Reusable Components with Directives There can be only one ngApp directive in the same HTML document that will be loaded and bootstrapped by the framework automatically. However, it's possible to have others as long as you manually bootstrap them. The ngController directive In our first application in Chapter 1, Getting Started with AngularJS, we used a controller called parkingCtrl. We can attach any controller to the view using the ngController directive. After using this directive, the view and controller start to share the same scope and are ready to work together, as shown in the following code: index.html [Packt] Parking There is another way to attach a controller to a specific view. In the following chapters, we will learn how to create a single-page application using the $route service. To avoid undesired duplicated behavior, remember to avoid the ngController directive while using the $route service. [ 20 ] Chapter 2 Nested controllers Sometimes, our controller can become too complex, and it might be interesting to split the behavior into separated controllers. This can be achieved by creating nested controllers, which means registering controllers that will work only inside a specific element of the view, as shown in the following code:
The scope of the nested controllers will inherit all the properties of the outside scope, overriding it in case of equality. The ngBind directive The ngBind directive is generally applied to a span element and replaces the content of the element with the results of the provided expression. It has the same meaning as that of the double curly markup, for example, {{expression}}. Why would anyone like to use this directive when a less verbose alternative is available? This is because when the page is being compiled, there is a moment when the raw state of the expressions is shown. Since the directive is defined by the attribute of the element, it is invisible to the user. We will learn these expressions in Chapter 3, Data Handling. The following is an example of the ngBind directive usage: index.html [Packt] Parking

[ 21 ] Creating Reusable Components with Directives The ngBindHtml directive Sometimes, it might be necessary to bind a string of raw HTML. In this case, the ngBindHtml directive can be used in the same way as ngBind; however, the only difference will be that it does not escape the content, which allows the browser to interpret it as shown in the following code: index.html [Packt] Parking

In order to use this directive, we will need the angular-sanitize.js dependency. It brings the ngBindHtml directive and protects the application against common cross-site scripting (XSS) attacks. The ngRepeat directive The ngRepeat directive is really useful to iterate over arrays and objects. It can be used with any kind of element such as the rows of a table, the elements of a list, and even the options of select. We must provide a special repeat expression that describes the array to iterate over the variable that will hold each item in the iteration. The most basic expression format allows us to iterate over an array, attributing each element to a variable: variable in array [ 22 ] Chapter 2 In the following code, we will iterate over the cars array and assign each element to the car variable: index.html [Packt] Parking

Plate Entrance
Also, it's possible to use a slightly different expression to iterate over objects: (key, value) in object [ 23 ] Creating Reusable Components with Directives Beyond iterating, we might need to identify which is the first or the last element, what is its index number, and many other things. This can be achieved by using the following properties: Variable Type Details $index number Number of the element $first Boolean This is true if the element is the first one $last Boolean This is true if the element is the last one $middle Boolean This is true if the element is in the middle $even Boolean This is true if the element is even $odd Boolean This is true if the element is odd The ngModel directive The ngModel directive attaches the element to a property in the scope, thus binding the view to the model. In this case, the element can be input (all types), select, or textarea, as shown in the following code: There is an important piece of advice regarding the use of this directive. We must pay attention to the purpose of the field that is using the ngModel directive. Every time the field is a part of the construction of an object, we must declare the object in which the property should be attached. In this case, the object that is being constructed is a car; so, we will use car.plate inside the directive expression. However, sometimes it may so happen that there is an input field that is just used to change a flag, allowing the control of the state of a dialog or another UI component. In this case, we can use the ngModel directive without any object as long as it will not be used together with other properties or even persisted. In Chapter 5, Scope, we will go through the two-way data binding concept. It is very important to understand how the ngModel directive works behind the scenes. [ 24 ] Chapter 2 The ngClick directive and other event directives The ngClick directive is one of the most useful kinds of directives in the framework. It allows you to bind any custom behavior to the click event of the element. The following code is an example of the usage of the ngClick directive calling a function: index.html [Packt] Parking

[ 25 ] Creating Reusable Components with Directives
Plate Entrance
In the preceding code, there is another pitfall. Inside the ngClick directive, we will call the park function, passing car as a parameter. As long as we have access to the scope through the controller, it would not be easy if we just accessed it directly, without passing any parameter at all. Keep in mind that we must take care of the coupling level between the view and the controller. One way to keep it low is to avoid reading the scope object directly from the controller and replacing this intention by passing everything it needs with the parameter from the view. This will increase controller testability and also make the things more clear and explicit. Other directives that have the same behavior but are triggered by other events are ngBlur, ngChange, ngCopy, ngCut, ngDblClick, ngFocus, ngKeyPress, ngKeyDown, ngKeyUp, ngMousedown, ngMouseenter, ngMouseleave, ngMousemove, ngMouseover, ngMouseup, and ngPaste. The ngDisable directive The ngDisable directive can disable elements based on the Boolean value of an expression. In this next example, we will disable the button when the variable is true: In Chapter 3, Data Handling, we will learn how to combine this directive with validation techniques. [ 26 ] Chapter 2 The ngClass directive The ngClass directive is used every time you need to dynamically apply a class to an element by providing the name of the class in a data-binding expression. The following code shows the application of the ngClass directive: index.html [Packt] Parking

[ 27 ] Creating Reusable Components with Directives
Plate Entrance
The ngOptions directive The ngRepeat directive can be used to create the options of a select element; however, there is a much more recommended directive that should be used for this purpose—the ngOptions directive. Through an expression, we need to indicate the property of the scope from which the directive will iterate, the name of the temporary variable that will hold the content of each loop's iteration, and the property of the variable that should be displayed. In the following example, we have introduced a list of colors: index.html [Packt] Parking [ 28 ] Chapter 2

[ 29 ] Creating Reusable Components with Directives
Plate Color Entrance
This directive requires the use of the ngModel directive. The ngStyle directive The ngStyle directive is used to supply the dynamic style configuration demand. It follows the same concept used with the ngClass directive; however, here we can directly use the style properties and its values: The ngShow and ngHide directives The ngShow directive changes the visibility of an element based on its display property:
[ 30 ] Chapter 2
Plate Color Entrance
The parking lot is empty
Depending on the implementation, you can use the complementary ngHide directive of ngShow. The ngIf directive The nglf directive could be used in the same way as the ngShow directive; however, while the ngShow directive just deals with the visibility of the element, the ngIf directive prevents the rendering of an element in our template. The ngInclude directive AngularJS provides a way to include other external HTML fragments in our pages. The ngInclude directive allows the fragmentation and reuse of the application layout and is an important concept to explore. The following is an example code for the usage of the ngInclude directive:
[ 31 ] Creating Reusable Components with Directives Refactoring application organization As long as our application grows with the creation of new components such as directives, the organization of the code needs to evolve. As we saw in the Organizing the code section in Chapter 1, Getting Started with AngularJS, we used the inline style; however, now we will use the stereotyped style, as shown in the following code: index.html [Packt] Parking

[ 32 ] Chapter 2
Plate Color Entrance
The parking lot is empty
Share: