Full Transcript

UQ23CA654B - Web Application Frameworks I Unit-4 Lecture Notes Architecting an Angular application List of topics that we're going to cover together: ✓ An Angular application as a tree of components ✓ The @Component annotation ✓ Properties of t...

UQ23CA654B - Web Application Frameworks I Unit-4 Lecture Notes Architecting an Angular application List of topics that we're going to cover together: ✓ An Angular application as a tree of components ✓ The @Component annotation ✓ Properties of the @Component annotation ✓ Content projection ✓ Life cycle hooks ✓ Component interface P.Sreenivas Asst.professor, Dept. of Computer Applications Page 1 UQ23CA654B - Web Application Frameworks I Unit-4 Lecture Notes Building Angular components Angular applications contain a single rootcomponent.While discussing about application's screens or views, it is necessary to mention other components that act as root components for that view.For example, the sign-up screen has a root component. Angular application architecture – a tree of components An Angular application is basically a tree ofcomponents. Angular is an SPA framework and thus has a single page to leverage for displaying its tree of components. Angular has a single top-level component, called the rootcomponent, and depending on what we'd like our applicationto do in response to our user's actions, we havethat root component load up other components. These other components (let's refer to them as secondary root components for now) in turn recursively render additional components. Architecting an Angular application Like in most of the engineering projects, software projects need to have a process for designing and architecting applications.The easiest way is to start to break down theapplication into smaller chunks. In Angular perspective, it means that we need to break down our application into separate components, each of which is responsible for certain activities.Once we have all lists of components that we need to use, we need to treat them as black boxes or mathematical functions. P.Sreenivas Asst.professor, Dept. of Computer Applications Page 2 UQ23CA654B - Web Application Frameworks I Unit-4 Lecture Notes Breaking up your components into sub-components The number of components in an application, or even per page, for that matter, varies greatly. It can range from just a few to several hundred—or maybe even more.There is a good rule of thumb for how far you shouldgo in breaking up a component. If you keep component reusability in mind, all you need to ask yourself as you break down the component into sub-components is this: "Are there two or more parts to this component that I can reuse elsewhere?“ If the answer is yes, you can probably benefit from breaking it down further. If the answer is no, then you're done—no morebreaking down of the component is necessary. Component Responsibilities Angular applications that are architected will have components that are not only reusable but have well- definedboundaries. The components should be abstracted away from oneanother, and they should not know about each other’sdetails (that is,implementation). The one thing that they should know about each other is how to communicate with each other. This is accomplished via their public interfaces. P.Sreenivas Asst.professor, Dept. of Computer Applications Page 3 UQ23CA654B - Web Application Frameworks I Unit-4 Lecture Notes Annotations, @Component Annotations Annotations are a new feature of TypeScript. They are symbols, prefixed with the @ sign, that we add to our code (that is, used to decorate our classes). Annotations can appear at the top of our class declaration, or at the top of our functions, or even on top of our class properties. What annotations do?? Generally speaking, is to inject boilerplate code where they are attached (that is, our class, function, or properties). @Component While annotations can appear at the top of our class declaration, or at the top of our functions, or even on top of our class properties, the @Component annotation will always appear at the top of our component's class declaration. In order for the @Component annotation to become available to us, we have to import it like this: import { Component } from '@angular/core'; It is JavaScript—specifically. Properties of the @Component decorator The @Component decorator provides us with a number of properties for the purposes ofconfiguring our components. P.Sreenivas Asst.professor, Dept. of Computer Applications Page 4 UQ23CA654B - Web Application Frameworks I Unit-4 Lecture Notes Selector The selector is a property of the @Component annotation, and its value (of type string) iswhat gives the name to our custom HTML tag. @Component({ selector: 'car' }) classCarComponent { } When Angular sees our custom HTML tags, , it creates an instance of our CarComponent and will replace our custom tags with some HTML that the browser actually understands. Template and TemplateUrl In the example given, the car component has no visible body just yet. This is because Angular needs to know what browser-friendly HTML to add when it renders our car component, and we just haven't provided that for Angular yet. The way to provide that is to use the templateproperty (of type string) to hold the HTML that Angular will render for us after it creates the instance of the CarComponent class (any time it sees our custom tags, ). @Component({ selector: 'car', template: 'What production car has the fastest acceleration time from 0 to 60?Tesla ' }) classCarComponent {} P.Sreenivas Asst.professor, Dept. of Computer Applications Page 5 UQ23CA654B - Web Application Frameworks I Unit-4 Lecture Notes What would happen if our component required a lot of HTML? Well, this is why we have another property that we can use, templateUrl. The templateUrl property provides us with a way to externalize our component's HTML from our component class and have it in a separate file. Your template property would look something like this: template: 'car.html Style and StyleUrl The styles property is used for what you expect it to be used for—to add styling to our component template. Just like the template property, the value is of type string. It's easiest to read CSS when spaced over multiple lines, the back-tick character is used(new in ES6, and thus also available in TypeScript), which enables us to create what is known as template literals. @Component({ selector: 'car', template: 'What production car has the fastest acceleration time from 0 to 60?Tesla ', styles: [`.car { color: #008000; font-weight: bold; } `] }) classCarComponent { } StyleUrl property works just like templateUrl property.It provides us with a way to externalize our component's CSS from our component class and having it in externalized style sheets. P.Sreenivas Asst.professor, Dept. of Computer Applications Page 6 UQ23CA654B - Web Application Frameworks I Unit-4 Lecture Notes The styleUrls property takes a value of an array of strings (as opposed to being of type String as what the value of the templateUrl property is)—thus, we can pass multiple style sheets to it if we wanted to.So, by using a combination of the template, templateUrl, styles, and styleUrls properties, we can encapsulate the HTML (that is, our component template), and the CSS we'd like to apply to our template, within our component class. Module vsNgModule The notion of modules is new in ES6. In JavaScript, when we talk about a module, we are usually referring to a code file that we can then import into the context of our executing script, making its encapsulated functions available to our script. An Angular module, or NgModule, is a module consisting of more than one file— hence, it's often referred to as a package. Because we treat this NgModule, or package, in much the same way as a JavaScript module—by importing it—we often think of them as being equivalent, but they are not. Properties of the @NgModule decorator There are four parameters in the @NgModule annotation on app module class in the file app.module.ts. Declarations: This is where we list the components and directives that we will need to package in this NgModule. Imports: These make the exported declarations of other modules available toourNgModule. Providers: This is where we list services and values so that they become known to dependency injection (DI). They are added to the root scope and are injected to other services or directives that have them as a dependency. P.Sreenivas Asst.professor, Dept. of Computer Applications Page 7 UQ23CA654B - Web Application Frameworks I Unit-4 Lecture Notes Bootstrap: This is where we list the component that we want Angular to Bootstrap upon application startup.There can only be one NgModule in our application where we make use of the Bootstrap parameter—since the bootstrapping process starts with only one module. Content Projection The notion of content projection provides component developers with a mechanism that can increase their reusability.What this means is that instead of trying to create a component that has properties for each possible way. Its template can be altered (which is nearly impossible) so that the developers that consume the component can vary the values of these properties to customize how it's rendered. Content projection provides a way to accomplish this with much less ceremony. The mechanism we use is a pair of ng-content tags, like this:. In Angular, content projection is used to project content in a component. Let’s take a closer look at how it works: Content projection allows you to insert a shadow DOM in your component.To put it simply, if you want to insert HTML elements or other components in a component, then you do that using the concept of content projection. In Angular, you achieve content projection using < ng-content >< /ng-content >. You can make reusable components and scalable applications by properly using content projection. Example: To understand content projection, let us consider GreetComponent as shown in the code listing below: import { Component } from '@angular/core'; @Component({ selector: 'greet', template: `{{message}}` }) export class GreetComponent { message: string = "Hello There !“} P.Sreenivas Asst.professor, Dept. of Computer Applications Page 8 UQ23CA654B - Web Application Frameworks I Unit-4 Lecture Notes Now if you use GreetComponent in another component, and want to pass a greeting message from the parent component, then you should use the @Input() decorator. This way, a modified GreetComponnet will look like the listing below: import { Component, Input } from '@angular/core'; @Component({ selector: 'greet', template: `{{message}}` }) export class GreetComponent { @Input() message: string; } Using the @Input() decorator, you can pass a simple string to the GreetComponnet, but what if you need to pass different types of data to the GreetComponent such as: ❑ Inner HTML ❑ HTML Elements ❑ Styled HTML ❑ Another Component, etc. To pass or project styled HTML or another component, content projection is used. Let us modify the GreetComponent to use content projection in this code: P.Sreenivas Asst.professor, Dept. of Computer Applications Page 9 UQ23CA654B - Web Application Frameworks I Unit-4 Lecture Notes We are using this to project content in the GreetComponent. When you use the GreetComponent, you’ll pass content as shown below: In the listing above, you are projecting styled HTML to the GreetComponent and you’ll get the following output: P.Sreenivas Asst.professor, Dept. of Computer Applications Page 10 UQ23CA654B - Web Application Frameworks I Unit-4 Lecture Notes ❖ This is an example of Single Slot Content Projection. Whatever you pass to the GreetComponent will be projected. ❖ ❖ In the same way, more components may be called from a single interface or components may be passed to other components, and can be get projected. Life Cycle Hooks Angular components also have a life cycle—the different stages, or phases, they go through from the moment they spring into existence to the moment they cease to exist. We can hook into these different stages to run any code that we may want to have Angular run for us as our component moves through them. This is made possible because Angular provides us with special methods, one for each phase of the component life cycle, which Angular calls for us. The following table enumerates the most common ones: P.Sreenivas Asst.professor, Dept. of Computer Applications Page 11 UQ23CA654B - Web Application Frameworks I Unit-4 Lecture Notes Most common life cycle hooks From the preceding list of life cycle hooks you can only three of them (in most cases). All three fall into the component type of life cycle hook: ngOnInit: Our initialization logic for our component will go here. You may think that the constructor is the place to add the initialization logic, but ngOnInit is preferable because any binding of data via our interface (that is, input properties) will have been done. This isn't the case with the constructor Phase. ngOnChanges: When we want to know what input properties have changed, and to what they were changed to, this is the place to look. ngOnDestroy: This is where we insert our cleanup logic for our component (if we have any things we'd like to clean up—otherwise, we don't use it). Example: class CarComponent { ngOnInit() { console.log('An instance of our CarComponent has been fully initialized.'); } } Component interface – inputs and outputs, and the flow of data Let's take a quick look at a concrete example—it'll show how a parent component could pass data to its child component. To demonstrate this, let's first create our two components. Here is our DadComponent, which will be the parent component: Example: import {Component } from '@angular/core'; @Component({ selector: 'dad', template: `Hello. {{message}}. `, }) export class DadComponent { message : string = "I'm a Dad"; arrSonNames = ['Justin','','Brendan']; } Here is our SonComponent, which will be the child component: P.Sreenivas Asst.professor, Dept. of Computer Applications Page 13 UQ23CA654B - Web Application Frameworks I Unit-4 Lecture Notes Templates What is a Template? ❖ Templates are going to define how your components are displayed, and laid out on web pages. ❖ Angular provides several built-in directives that provide developers control over the display of their components. Templating syntax in Angular provides us with a mechanism to make our HTML dynamic specifically, for data binding, property binding, and event binding. The way in which Angular gives the power to create templates that produce dynamic HTML, or to manipulate the DOM, is through a set of symbols. Here are the six basic symbols that we can use: {{ }} for string interpolation and one-way data binding [( )] for two-way data binding # for variable declaration ( ) for event binding [ ] for property binding * prepends structural directives, such as ngFor, P.Sreenivas Asst.professor, Dept. of Computer Applications Page 14 UQ23CA654B - Web Application Frameworks I Unit-4 Lecture Notes Template View Template Syntax In Angular, a template is a chunk of HTML. Within a template, you can use special syntax to leverage many of Angular's features. Prerequisites: Before learning template syntax, you should be familiar with the following: ❑ Angular concepts ❑ JavaScript ❑ HTML ❑ CSS Each Angular template in your app is a section of HTML that you can include as a part of the page that the browser displays. An Angular HTML template renders a view, or user interface, in the browser, just like regular HTML, but with a lot more functionality. P.Sreenivas Asst.professor, Dept. of Computer Applications Page 15 UQ23CA642B WEB APPLICATION FRAMEWORKS-I When you generate an Angular app with the Angular CLI, the app.component.html file is the default template containing placeholder HTML. The template syntax guides show you how you can control the UX/UI by coordinating data between the class and the template. A template looks like regular HTML, except that it also contains Angular template syntax, which alters the HTML based on your app's logic and the state of app and DOM data. Your template can use data binding to coordinate the app and DOM data, pipes to transform data before it is displayed, and Directives to apply app logic to what gets displayed. Example: Hero List Pick a hero from the list {{hero.name}} This template uses typical HTML elements like and , and also includes Angular template-syntax elements, *ngFor, {{hero.name}}, (click), [hero], and. The template-syntax elements tell Angular how to render the HTML to the screen, using program logic and data. The *ngFor directive tells Angular to iterate over a list. {{hero.name}}, (click), and [hero] bind program data to and from the DOM, responding to user input. The tag in the example is an element that represents a new component, HeroDetailComponent. P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 16 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Data binding Without a framework, you would be responsible for pushing data values into the HTML controls and turning user responses into actions and value updates. Writing such push and pull logic by hand is tedious, error-prone, and a nightmare to read, as any experienced front-end JavaScript programmer can attest. Angular supports two-way data binding, a mechanism for coordinating the parts of a template with the parts of a component. Add binding markup to the template HTML to tell Angular how to connect both sides. The following diagram shows the four forms of data binding markup. Each form has a direction: to the DOM, from the DOM, or both. This example from the HeroListComponent template uses three of these forms. {{hero.name}} The {{hero.name}} interpolation displays the component's hero.name property value within the element. The [hero] property binding passes the value of selectedHero from the parent HeroListComponent to the hero property of the child HeroDetailComponent. The (click) event binding calls the component's selectHero method when the user clicks a hero's name. P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 17 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Directives, Built-in Directives What are Directives? ▪ Angular directives are constructs that provide specific DOM manipulation operations. ▪ Actually, a component is a directive… ▪ When we are saying components are building blocks of angular application, we are indirectly saying directives are building blocks of angular application. ▪ It also helps you to extend HTML.. A directive is a function that executes whenever the Angular compiler finds it in the DOM. Angular directives are used to extend the power of the HTML by giving it new syntax. o Each directive has a name — either one from the Angular predefined like ng-repeat, or a custom one which can be called anything. Each directive determines where it can be used: In an element, attribute, class or comment. Use Angular's built-in directives to manage forms, lists, styles, , Angular directives are separated into three different types: P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 18 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Component Directives, Structural Directives Component Directives: Component directives are used in main class. They contain the detail of how the component should be processed, instantiated and used at runtime. The other two directive types don’t have templates. Instead, they’re specifically tailored to DOM manipulation. P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 19 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Structural Directives Structural Directives: Structural directives start with a * sign. These directives are used to manipulate and change the structure of the DOM elements. For example, *ngIf directive, *ngSwitch directive, and *ngFor directive. ngIf Directive: The ngIf allows us to Add/Remove DOM Element. *ngSwitch Directive: The *ngSwitch allows us to Add/Remove DOM Element. It is similar to switch statement of C#. *ngFor Directive: The *ngFor directive is used to repeat a portion of HTML template once per each item from an iterable list (Collection). Attribute directives Attribute directives manipulate the DOM by changing the appearance or the behavior of specific DOM elements. These types of directives are surrounded by brackets, and are attributes of an HTML element. example: ngClass directive, and ngStyle directive etc. ngClass Directive: The ngClass directive is used to add or remove CSS classes to an HTML element. ngStyle Directive: The ngStyle directive facilitates you to modify the style of an HTML element using the expression. You can also use ngStyle directive to dynamically change the style of your HTML element. ❑ The brackets are symbols and they signal to Angular that it may need to change either the appearance or the behavior of the element for which the directive is an attribute of. ❑ Ex: This element, and its contents, will be hidden for all users that are not Admins. P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 20 UQ23CA642B WEB APPLICATION FRAMEWORKS-I ❑ The directive referring to is named hidden, and will cause Angular to either show or hide its element. The hidden attribute directive is associated with an expression to be evaluated. The expression must evaluate to a Boolean (either true or false). Structural Directives in detail The syntax we use to signal to Angular that we have a structural directive it needs to pay attention to is the asterisk (*). Structural directives are prefixed with an asterisk, which signals to Angular that it may need to add or remove elements from the DOM. Structural Directive Attribute Directive The component has their view (HTML Structural directives are applied to and styles) because of that, there can be elements and used to add or one component on a host element, but remove content (stamp and template). multiple directives. NgFor {{ car.make }}: {{ car.model }} The *ngFor structural directive. Let's take a look at these in bullet-point form: ❖ ngFor takes an iterable, and loops through it, adding elements to the DOM. ❖ The general form of the directive's syntax is *ngFor="let of “ ❖ NgFor (note the capital N) refers to the class that defines the directive. P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 21 UQ23CA642B WEB APPLICATION FRAMEWORKS-I ❖ ngFor (note the lower case n) refers to both the attribute name, as well as it being an instance of the NgFor class. ❖ The rest of the structural directives follow the same casing convention as NgFor. ❖ We can nest ngFor (in much the same way that we can have nested for each...i n loops) Built_in Directives The various built-in directives are ❖ NgFor ❖ NgIf ❖ NgSwitch, NgCase, and NgDefault ❖ NgStyle ❖ NgClass ❖ NgNonBindable NgIf When we want to either display or remove an element from the DOM, we use the NgIf directive. We pass an expression to the directive, and it must evaluate to a Boolean. If it evaluates to true, the element will be displayed on the view. Conversely, if the expression evaluates to false, the element will be removed from the DOM. We can also bind to the hidden property to achieve the same thing, There is a difference between the property binding method, and using the NgIf directive. ❑ The difference is that using property binding on hidden just hides the element, whereas using the NgIf directive physically removes the element from the DOM. P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 22 UQ23CA642B WEB APPLICATION FRAMEWORKS-I The {{ car.make }} {{ car.model }} is over 350 HP. NgSwitch, NgCase, and NgDefault ❖ In several programming languages, such as Java, JavaScript, and TypeScript, the switch statement does not work in isolation. It works in concert with other statements and keywords—namely, case and default. ❖ Angular's NgSwitch directive works exactly the same way, in that NgSwitch works in concert with NgCase and NgDefault. Example @Component({ selector: 'ngswitch-example', template: `NgSwitch (1) {{ person.name }} ({{ person.country }}) {{ person.name }} ({{ person.country }}) {{ person.name }} ({{ person.country }}) {{ person.name }} ({{ person.country }}) P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 23 UQ23CA642B WEB APPLICATION FRAMEWORKS-I }) class NgSwitchExampleComponent { people: any[] = [ { "name": "Douglas Pace", "age": 35, "country": 'MARS' }, { "name": "Mcleod Mueller", "age": 32, "country": 'USA' }, { "name": "Day Meyers", "age": 21, "country": 'HK' }, { "name": "Aguirre Ellis", "age": 34, "country": 'UK' }, { "name": "Cook Tyson", "age": 32, "country": 'USA' } ];} In the above example, P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 24 UQ23CA642B WEB APPLICATION FRAMEWORKS-I 1. We bind an expression to the ngSwitch directive. 2. The ngSwitchCase directive lets us define a condition which if it matches the expression in (1) will render the element it’s attached to. 3. If no conditions are met in the switch statement it will check to see if there is an ngSwitchDefault directive, if there is it will render the element that’s attached to, however it is optional — if it’s not present it simply won’t display anything if no matching ngSwitchCase directive is found. The key difference between the ngIf solution is that by using NgSwitch we evaluate the expression only once and then choose the element to display based on the result. Data binding using NgModel Directive There are two types of Data binding. ❑ One Way data binding ❑ Two Way data binding One Way Data Binding One-way data binding is done using the double curly braces symbol, {{ }}. One- way (that is, from the component class to the template), converted to a string, and rendered. The variable that we enclose within the double curly braces is bound d to the view. It does not allow for binding any changes back to the component class. ❖ Ex: app.component.ts import { Component } from "@angular/core"; @Component({selector:'app-example', template: ` {{firstName}} {{lastName}} ` }) export class AppComponent { firstName: string = "Yallaling"; lastName:string = "Goudar"; } One-way data binding from view to the component can be achieved by using the event binding technique. P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 25 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Let's consider an example where within parentheses on the left of the equal sign we have the target event like "click" and on the right side we may have the template statements such as component properties and methods(myFunction() in this case) bind to the event. (click)="myFunction()">Show alert app.component.ts import { Component } from "@angular/core"; @Component({ selector: 'app-example', template: `Show alert` }) export class AppComponent { myFunction(): void { alert('Show alert!'); } } Two Way Data Binding Two-way data binding in Angular will help users to exchange data from the component to view and from view to the component. It will help users to establish communication bi-directionally. In order for us to implement two-way data binding, thereby also allowing the binding of changes within the view back to the component class, we have to use the NgModel directive.It is bound two-way (that is from component to template and template to component). In order to use NgModel, we have to first import an Angular module named FormsModule from the forms package, like this: import { FormsModule } from '@angular/forms'; Then, to use this directive, we have to implement like this: P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 26 UQ23CA642B WEB APPLICATION FRAMEWORKS-I The above code cause the view template to display the value of my_content in the component class, but any changes to this div within the view template would be then be bound back to the component class. app.module.ts import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; import { FormsModule } from "@angular/forms"; @NgModule({imports:[BrowserModule, FormsModule], declarations: [ AppComponent], bootstrap: [AppComponent] }) export class AppModule { } After importing the FormsModule, you can go ahead and bind data using (ngModel) as shown below. import { Component } from '@angular/core'; @Component({ selector: 'app-example', template: ` Enter the value : Entered value is: {{val}} ` }) export class AppComponent { val: string = ''; } If you do not import the FormsModule, then you will get Template parse errors and it will result in this error: "Can't bind to 'ngModel' since it is not a known property of 'input'". Event Binding and Property Binding Data Binding can be implemented through Event binding and Property binding, apart from one-way and two-way. To bind an event that we're interested in listening for on an element, we enclose the event name within parentheses (which are one of our special symbols that we can use in our template syntax). To do so, we assign a statement to be run when the event is triggered. P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 27 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Here is an example of a JavaScript alert that will be triggered when someone clicks within the element: This text will not show. we enclose the property we want to set within square brackets (which are one of the special symbols that we can use in our template syntax). Ex: Property binding import {Component} from "@angular/core"; @Component({ selector: 'app- example', template: ` }) export class AppComponent { firstName: string = "Yallaling"; } Custom Directives Angular is extensible.We easily create our own custom components (so that We’re not restricted to using ready-made components from third parties), but we can also create our own attribute directives so that we're not restricted to what Angular gives us out of the box. Pipes Pipes are used for formatting the data in our template views. Pipes will take data as input and transform it into our desired format for displaying it to end user. We can use the pipe property (|) in any Angular template or view in our project. Let's say that, from the backend service, we get the price of a product as 100, and based on the user's country or preference, we may want to display the value as $100 if the user is from the USA, or INR 100 if the user is from India. So, we are able to transform the way that we display the price without any major complexity. In this case we use currency pipe operator. P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 28 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Angular provides a lot of built-in pipes ready to use directly in our templates. We can also create our own custom pipes to extend our application's functionality. List of Pipes are: ❖ Lowercase pipe ❖ Uppercase pipe ❖ Date pipe ❖ Currency pipe ❖ JSON pipe ❖ Percent pipe ❖ Decimal pipe ❖ Slice pipe Some data is needed that we want to process and transform using our pipes, create a dataset in our app.component.ts. products: any[] = [{ "code": "p100", "name": "Moto", "price": 390.56 }, {"code": "p200", "name": "Micro", "price": 240.89 }, {"code": "p300", "name": "Mini", "price": 300.43 }]; A sample dataset for products in our app component is been created. The pipes are supposed to be applied in app.component.html. We are going to keep it simple in our template. We will just create a table and bind the values in the table. P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 29 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Learning Angular Pipes Product Code Product Name Product Price {{product.code}} {{product.name}} {{product.price}} In the preceding sample code, we have created a table and, using the data binding, we have bound the data in our template. In the template, it is time to use pipe operators. To apply any pipe, we will have to add the pipe operator against the data, as shown in the following syntax: {{ data | }} We can easily transform our product name into uppercase by applying the uppercase pipe, as follows: {{product.name | uppercase }} Similarly, we can apply the lowercase pipe as well, which will make all characters lowercase: {{product.name | lowercase }} For displaying product prices, we want to add the currency; no problem, we will use the currency pipe: {{product.price | currency }} P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 30 UQ23CA642B WEB APPLICATION FRAMEWORKS-I To pass parameters to pipes we have to extend the syntax of pipe operator by passing parameters as follows: {{data | pipe : }} We can define a pipe operator with any number of parameters based on our requirements. We have used the currency operator in the previous example, so let's pass parameters to extend the currency pipe operator: {{ product.price | currency: 'INR' }} Angular Forms (Template Driven) , Important Modules and Building Login form What are Angular Forms? Angular Forms are a crucial component of practically any version of Angular app, especially enterprise apps like dashboards, live data apps, and data collecting. Throughout the evolution of Angular versions, its forms module has undergone remarkable enhancements, enabling developers to create sophisticated and user- friendly web forms effortlessly. Why Do We Need Angular Forms? Angular forms are widely used in applications for user login purposes, to upload certain information, update profiles, to apply for different fields, and to perform more data entry tasks. Nevertheless, validation, recording user inputs, and showing error messages can also be achieved using forms in Angular. With respect to the handling of shapes, form builder Angular forms has two approaches 1. Template-Driven Forms 2. Reactive Forms P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 31 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Both the above approaches of forms in Angular have a few common building blocks holding the following attributes: FormControl: mainly used for monitoring user input and for authenticating the individual form control. FormGroup: used to track the same values and authentication status for a collection of a form of control. FormArray: Array tracks the same values and status for the array of the form control. ControlValueAccessor: used to develop a distance between form builder Angular native DOM and form control elements. Forms Forms are heart of any application and are the main building blocks to gather, view, capture and process data provided by the users. The two approaches provided by Angular for building forms are as follows: Template-driven forms: HTML and data binding defined in template files P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 32 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Reactive or model-driven forms: Using model and validation in the Component class files. The main difference between reactive forms and template-driven forms, when it comes to the template, is in the data binding. In template-driven forms, we use two-way data binding to bind our data model directly to the form elements. On the other hand, with reactive forms, we bind our data model to the form itself (as opposed to its individual form elements). Template-driven forms Template-driven forms, as the name suggests, involve all the heavy-duty work of forms being performed right inside the template of the component. The approach is good and is recommended when dealing with simple, straightforward forms, without much complex validation or rules. All the logic is in the template files, which essentially means that we will make use of HTML elements and attributes. With template-driven forms, we use HTML to create the form and the input elements and create validation rules as HTML attributes. Two-way data binding is the key part, so we can tie the form elements to the properties in the Component class. Angular automatically tracks the form and input element states by generating the form model automatically for us to use. We can directly take the form as an object and process data easily. When using the template-driven approach, we first import the FormsModule, so we can have access to the following directives: ngForm ngModel ngModelGroup Template Driven Forms –Pros Template-driven forms can be very useful and helpful if the forms in our application are simple and straight forward with less metadata and validations. P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 33 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Template-driven forms are very easy to use. Suitable for simple and straightforward use cases. Easy-to-use two-way data binding, so there is minimal code and complexity. Angular automatically tracks the form and input element state. (you can disable the Submit button if the form's state is not complete). Template Driven Forms –Cons Not recommended if the form has complex form validations or require custom form validations Unit testing cannot be fully covered to test all use cases Important Modules Template-driven forms are mostly defined in the template file. We should understand some of the most important concepts related to forms, namely, ngForm and ngModel: ngForm: This is the directive that helps to create the control groups inside the form directive. ngModel: When ngModel is used on elements inside ngForm, all the elements and data get registered inside ngForm If the Angular form is using ngForm and ngModel, it means that the form is template- driven. P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 34 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Building our Login form 1. Create an angular application ng new template-driven-form --style=css –ssr=N 2. create a component test and connect to app ng g c login app.comonent.ts import { Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; import { FormsModule } from '@angular/forms'; import {NgForm} from '@angular/forms'; import { LoginComponent } from "./login/login.component"; @Component({ selector: 'app-root', standalone: true, imports: [RouterOutlet,FormsModule,LoginComponent], templateUrl: './app.component.html', styleUrl: './app.component.css' }) export class AppComponent { title = 'template-driven-form'; onSubmit(form: NgForm) { console.log('Your form data : ', form.value); } } app.comonent.html P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 35 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Angular template-based contact form Name: Email: Feedback: login.comonent.ts import { Component } from '@angular/core'; import { FormsModule } from '@angular/forms'; import {NgForm} from '@angular/forms' @Component({ selector: 'app-login', standalone: true, imports: [FormsModule], templateUrl: './login.component.html', styleUrl: './login.component.css' }) export class LoginComponent { username:string=''; password:string=''; login(loginForm:any){ //console.log(loginForm); //Display value in Object /Json Format P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 36 UQ23CA642B WEB APPLICATION FRAMEWORKS-I console.log(loginForm.value); //Dislay valid or invalid format console.log(loginForm.valid); //input element has beemn clicked /touched by mouse curser console.log(loginForm.touched); } } login.comonent.html login works! Login Username: Password: Sign-in Run the application: ng serve P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 37 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Let's analyze the preceding code in depth. We are creating a form using the HTML input elements and adding a username, password, and Submit button to the form. Template that use ngForm group all the input elements of the form together into the #loginForm template variable. For the input elements, we have added the ngModel attribute and we specify the name attribute for the elements. Using ngForm, we can now easily retrieve the value of the elements inside the form. A new local variable login Form template has been created. loginForm has the following properties: loginForm.value: Returns the object containing all the values of the input elements inside the form. loginForm.valid: Returns if the form is valid or not, based on the HTML attribute validators applied in the template. loginForm.touched: Returns true or false depending on whether the form was touched/edited by the user or not. In the preceding code, we are passing login Form.value to the component. We can pass any of these values to the component for processing or validation. Notice that we are also calling a login method, which we need to implement in our P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 38 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Component class file. Reactive Forms or Model-driven Forms Reactive forms are also called model-driven forms. In model-driven forms, the model is created in the Component class file and is responsible for doing the form validation, processing data, and much more. Angular internally builds a tree structure of the Angular form controls, which makes it much easier to push and manage data between the data models and the UI elements. We need to build the form model in our Component class by creating the instances of the building blocks (that is, FormControl and FormGroup). Additionally, we write the validation rules and the validation error messages in the class as well. Template-driven forms put the responsibility for the forms on the template, whereas reactive forms shift the responsibility for validation to the Component class. Pro’s Reactive forms are very useful in creating, validating and applying custom form validations to our forms in our applications. We can easily trust the model driven approach to do all the heavy-duty work that is usually associated with any complex forms. Greater flexibility for more complicated validation scenarios and custom, complex form validations. The data model is immutable. Since the data model is immutable, no data binding is done. It's easier to add input elements dynamically (such as subtasks on a task form) using form arrays. It's easy to bind various events to input elements using HostListener and HostBindings. All the code for the form controls and validations is inside the component, which makes templates much simpler and easier to maintain. P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 39 UQ23CA642B WEB APPLICATION FRAMEWORKS-I It's easier to unit test. Con’s While the pros and advantages of using reactive forms can certainly outweight the cons but still it's important to learn and understand the cons of using reactive forms in our applications. Immediatebeginners may find the initial learning curve too high. The developer is expected to have knowledge about the various modules required to work with model- driven forms, such as ngvalidators, and so on. Model-driven Forms (Important Modules) We create the model using the two powerful classes provided by Angular— formGroup and formControl: FormControl: Tracks the value and state of individual form input elements. FormGroup: Tracks the value and state of a group of form controls. FormBuilder: Helps us to develop forms with their initial value and their validations. @component P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 40 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Angular Forms- Validation Since we are working on data which is received from users, it's very important to make sure that the data we receive from our users is correct and valid. For example, when we expect the user to enter an email address, we should not allow spaces or a few special characters in the email address. One more example, if we request the user to enter the phone number, it should not have more than 10 digits (excluding country code of course) There can be many such custom valid checkpoints that we may want to have in our forms. In the template-driven forms, validation is done in the template itself using the HTML attributes. We can use any of the HTML attributes, such as required, maxlength, minlength, size, email, number, length, and so on, to put validation in forms. We can also make use of HTML pattern attributes to put regular expression checks in our form elements. There are various classes that we can make use of readily to implement validation in our forms: ng-touched: Input controls have been visited ng-untouched: Input controls have not been visited ng-dirty: Input controls data was changed ng-pristine:Input controls data has not been changed/updated. ng-valid: Input control data is a valid set and makes the form valid. ng-invalid: Input control data is not valid and hence the form is not valid. P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 41 UQ23CA642B WEB APPLICATION FRAMEWORKS-I In template-driven forms, Angular will automatically track the state of each input element and the state of the form as well. Hence, we can also use the preceding classes in our CSS/SCS to style/design our error notifications, as follows: 1.Create an angular application ng new reactive-form --style=css –ssr=N 2.create a component test and connect to app ng g c login app.comonent.ts import { Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; import { FormsModule,ReactiveFormsModule } from '@angular/forms'; //Import angular' FormGroup and FormBuilder classes import { FormGroup, FormBuilder } from '@angular/forms'; @Component({ selector: 'app-root', standalone: true, //import array of FormsModule and ReactiveFormsModule imports: [RouterOutlet,FormsModule,ReactiveFormsModule], templateUrl: './app.component.html', styleUrl: './app.component.css' }) export class AppComponent { title = 'reactive-form'; //contactForm used to hold our form object (instance of FormGroup) contactForm:any= FormGroup; //Inject FormBuilder via the component constructor: constructor(private formBuilder: FormBuilder) //Build the form with angular' FormBuilder {//createContactForm() method builds the form this.createContactForm(); } createContactForm(){ //call the method on the constructor: this.contactForm = this.formBuilder.group({ fullName: [''], email: [''], message: [''] }); } onSubmit() { console.log('Your form data : ', this.contactForm.value ); } } app.comonent.html Angular reactive contact form example Name: Email: Feedback: Angular template-based contact form Name: P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 43 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Email: Feedback: login.component.css input.ng-invalid { border:2px solid green; } login.comonent.ts import { Component } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { NgForm } from '@angular/forms' import { CommonModule } from '@angular/common'; @Component({ selector: 'app-login', standalone: true, imports: [ FormsModule, CommonModule ], templateUrl: './login.component.html', styleUrl: './login.component.css' }) export class LoginComponent { username:string=''; password:string=''; login(loginForm:any){ //console.log(loginForm); //Display value in Object /Json Format console.log(loginForm.value); //Dislay valid or invalid format P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 44 UQ23CA642B WEB APPLICATION FRAMEWORKS-I console.log(loginForm.valid); //input element has beemn clicked /touched by mouse curser console.log(loginForm.touched); } } login.comonent.html login works! Login Username : enter username Password: Sign- in Integrate Bootstrap in your Application for better output design 1. Go to the simple-routing command prompt and install Bootstrap npm install bootstrap@latest 2. After installing this package go into your angular.json file and add these lines into this object. "styles": [ "src/styles.css", "node_modules/bootstrap/scss/bootstrap.scss" ], "scripts": [ "node_modules/bootstrap/dist/js/bootstrap.bundle.min.js" ] Run the application: ng serve P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 46 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Angular generates a form model in both approaches, be it template-driven forms or reactive forms. The form model holds the data of the form elements and the state of the form elements. Submitting Form Data In the previous sections, where we have implemented our forms, we have created a method to call on ngSubmit. For our template-driven login form, we added the following code to our login.component.ts file: login(loginForm) { console.log(loginForm); console.log(loginForm.username); } We are passing the entire form object to the login method. Now the loginForm object will have all the details of the form controls, as well as the states. In our registration form, which is generated using a model-driven approach, we have used the instance of formGroup that we created in our Component class register.component.ts file. The following is the code we have added for capturing and processing the data: If you notice, for reactive forms, we do not have to pass any form data, since we had created the registerForm instance of FormGroup, so it's available in our class using the this operator. Once we have captured the data provided to the user, based on the application requirements, we can now implement our custom logic inside the component. Some of the common activities we do once we capture data are the following: P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 47 UQ23CA642B WEB APPLICATION FRAMEWORKS-I Securing data to make sure that we do not allow junk data into our system. Processing/enhancing the data, such as converting the password into an encrypted value. Checking for any automated bots processing our applications. Making HTTP calls to backend services using Angular services. P.Sreenivas, Asst.professor, Dept. of Computer Applications Page 48

Use Quizgecko on...
Browser
Browser