What is Angular?
In a nutshell, it is a type of web framework that is used to create efficient single-page web
applications from scratch. Angular and its components are built on the typescript. As Angular
works on various types of components we also call Angular a component-based framework.
The major purpose for developing Angular was to find an alternative to Angular.Js.
It is an upgraded version of the same. Its architecture depends on NgModules which
provides a structure for the associated commands and different components of Angular.
Angular is capable of developing both single developer-based applications as well as
organizational-based applications sophisticatedly.
Angular also provides platforms for other types of technologies to be built upon.
Applications developed on Angular are seen to be highly scalable.
Why should we consider Angular?
It’s been quite a while since Angular was published since its first release there are a lot of
updates have taken place. Because of these changes, it is still the to-go language for developers.
Consider the below-mentioned points for which Angular is still in demand:
Angular is well documented from the beginning and it is still maintained to date by
Google and associated community members.
It is a typescript-based framework, has a rich library source, and is very similar to
javascript.
Angular has extended support from HTML which helps in better development of
different components.
JavaScript code generation is possible, the generated code is highly optimized and robust.
The creation of templates is possible in Angular, this promotes code reusability and
speeds up the development process.
Angular-based codes are high in performance and have less execution time.
What is TypeScript?
TypeScript (TS) is superset of JavaScript developed by Microsoft. TypeScript is supported by
two companies Microsoft and Google.
Microsoft because it is the creator of TypeScript and by Google as it was used to develop
Angular from version2 to Angular12 (the current version). It is official language to build
Angular2+ apps.
TypeScript is developed on the top of JavaScript. It supports all the concepts and features of
JavaScript.
TypeScript is to create a super-set of JavaScript. It provides powerful OOP (Object Oriented
Programming) features like inheritance interfaces and classes, a declarative style, static typing,
and modules. Although many of these features are already in JavaScript, they are different as
JavaScript follows a prototypical-based OOP, not class-based OOP.
TS features make it easy for developers to create complex and large JavaScript applications that
are easier to main and debug.
TypeScript can be work with both client-side programming and server-side programming.
TypeScript can be used in client-side program development, using Angular framework. It can be
used in server-side program development, using NodeJS platform.
To work with TypeScript, we require to be used in modern code editors / IDE's, such as Visual
Studio Code, Atom, Sublime Text, Web Storm, Eclipse etc.
As we know browser only understand JavaScript language. Browser doesn’t support TypeScript.
TypeScript code can’t be executed directly by the browser.
So, TypeScript code should be converted into JavaScript code, and we have to import JavaScript
language file into the web page. Browser executes JavaScript. We use "TypeScript Compiler"
(tsc) to compile / transpile "filename.ts (TypeScript file)" to "filename.js (JavaScript file)". We
won't load TypeScript file into the browser. We will load & execute JavaScript file into the
browser
TypeScript is a compiled language which means we’ll need to transpile it into JavaScript to be
able to run it in web browsers which do only understand one programming language.
Fortunately, the TS transpiler integrates well with the majority of build systems and bundlers.
TypeScript file ends with .ts extension. We can install the TypeScript compiler using npm and
then you can call it by running the tsc source-file.ts command from the terminal.
AngularJS
AngularJS, is a javascript based open-source front-end framework and is mainly used to develop
single page applications on web. It enriches the static HTML to dynamic HTML. It extends
existing HTML by providing directives. Its latest stable version is 1.7.7
Angular
Angular is alternative to AngularJS and it is a major version upgrade to Angular JS. Angular
release starts from 2.0. It is very fast as compared to AngularJS. It has modular design, have
angular CLI and easy to develop. Angular latest stable version is 9.
Following are the important differences between AngularJS and Angular.
Sr. No. Key AngularJS Angular
1 Architecture AngularJS works on MVC, Model View Angular uses components
Sr. No. Key AngularJS Angular
Controller Design. Here View shows the and directives. Here
information present in the model and controller component is directive
processes the information. with a template.
Angular code is written in
2 Language AngularJS code is written in javascript.
typescript.
Angular develped
3 Mobile AngularJS code is not mobile friendly. applications are mobile
browser friendly.
{{}} are used to bind data between view and () and [] attributes are
Expression
4 model. Special methods, ng-bind can also be used to bind data between
syntax
used to do the same. view and model.
Dependency Hiearchical DI system is
5 DI is not used.
Injection used in Angular.
@Route configuration is
@routeProvider.when, then are used to provide
6 Routing used to define routing
routing information.
information.
Angular code is better
AngularJS project is difficult to manage with structured, is easy to
7 Management
increasing size of the source code. create and manage bigger
applications.
Features of Angular
1. Document Object Model
DOM (Document Object Model) treats an XML or HTML document as a tree structure in which
each node represents a part of the document.
Angular uses regular DOM. Consider that ten updates are made on the same HTML page.
Instead of updating the ones that were already updated, Angular will update the entire tree
structure of HTML tags.
2. TypeScript
TypeScript defines a set of types to JavaScript, which helps users write JavaScript code that is
easier to understand. All of the TypeScript code compiles with JavaScript and can run smoothly
on any platform. TypeScript is not compulsory for developing an Angular application. However,
it is highly recommended as it offers better syntactic structure—while making the codebase
easier to understand and maintain.
3. Data Binding
Data binding is a process that enables users to manipulate web page elements through a web
browser. It employs dynamic HTML and does not require complex scripting or programming.
Data binding is used in web pages that include interactive components, such as calculators,
tutorials, forums, and games. It also enables a better incremental display of a web page when
pages contain a large amount of data.
Angular uses the two-way binding. The model state reflects any changes made in the
corresponding UI elements. Conversely, the UI state reflects any changes in the model state. This
feature enables the framework to connect the DOM to the model data through the controller.
4. Testing
ngular uses the Jasmine testing framework. The Jasmine framework provides multiple
functionalities to write different kinds of test cases. Karma is the task-runner for the tests that
uses a configuration file to set the start-up, reporters, and testing framework.
Now that you’re familiar with Angular’s basic features, you need to understand its architecture if
you want to work with Angular daily. You can also expand your Angular knowledge by taking
the Angular Certification Training Course and learning concepts such as TypeScript, Bootstrap
Grid System, dependency injections, SPA, forms, pipes, promises, observables, and Angular
class testing.
Advantages of Angular
Many versions of Angular have been released since its inception. All these versions have added
to the efficient working of the framework.
1. Custom Components
Angular enables users to build their own components that can pack functionality along with
rendering logic into reusable pieces. It also plays well with web components.
2. Data Binding
Angular enables users to effortlessly move data from JavaScript code to the view, and react to
user events without having to write any code manually.
3. Dependency Injection
Angular enables users to write modular services and inject them wherever they are needed. This
improves the testability and reusability of the same services.
4. Testing
Tests are first-class tools, and Angular has been built from the ground up with testability in mind.
You will have the ability to test every part of your application—which is highly recommended.
5. Comprehensive
Angular is a full-fledged framework and provides out-of-the-box solutions for server
communication, routing within your application, and more.
6. Browser Compatibility
Angular is cross-platform and compatible with multiple browsers. An Angular application can
typically run on all browsers (Eg: Chrome, Firefox) and OSes, such as Windows, macOS, and
Linux.
Limitations of Angular
1. Steep Learning Curve
The basic components of Angular that all users should know include directives, modules,
decorators, components, services, dependency injection, pipes, and templates. More advanced
topics include change detection, zones, AoT compilation, and Rx.js. For beginners, Angular 4
may be challenging to learn because it is a complete framework.
2. Limited SEO Options
Angular offers limited SEO options and poor accessibility to search engine crawlers.
3. Migration
One of the reasons why companies do not frequently use Angular is the difficulty in porting
legacy js/jquery-based code to angular style architecture. Also, each new release can be
troublesome to upgrade, and several of them are not backward-compatible.
4. Verbose and Complex
A common issue in the Angular community is the verbosity of the framework. It is also fairly
complex compared to other front-end tools.
Core Concepts of Angular
Modules
Angular applications are modular and Angular has its own modularity system called NgModules.
NgModules are containers for a cohesive block of code dedicated to an application domain, a
workflow, or a closely related set of capabilities. They can contain components, service
providers, and other code files whose scope is defined by the containing NgModule. They can
import functionality that is exported from other NgModules, and export selected functionality for
use by other NgModules.
Every Angular application has at least one NgModule class, the root module, which is
conventionally named AppModule and resides in a file named app.module.ts. You launch your
application by bootstrapping the root NgModule.
While a small application might have only one NgModule, most applications have many more
feature modules. The root NgModule for an application is so named because it can include child
NgModules in a hierarchy of any depth.
NgModule metadata
An NgModule is defined by a class decorated with @NgModule(). The @NgModule() decorator
is a function that takes a single metadata object, whose properties describe the module. The most
important properties are as follows.
Properties Details
declarations The components, directives, and pipes that belong to this NgModule.
The subset of declarations that should be visible and usable in the component
exports
templates of other NgModules.
imports Other modules whose exported classes are needed by component templates
Properties Details
declared in this NgModule.
Creators of services that this NgModule contributes to the global collection of
providers services; they become accessible in all parts of the application. (You can also
specify providers at the component level.)
The main application view, called the root component, which hosts all other
bootstrap
application views. Only the root NgModule should set the bootstrap property.
src/app/app.module.ts
Here's a simple root NgModule definition.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
imports: [ BrowserModule ],
providers: [ Logger ],
declarations: [ AppComponent ],
exports: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Declaration array In module
declaration array contains the components, directives and pipes of the particular module. If you
are creating a custom pipe, component or directive this is the array which you need to use to add
those before using in the component.
declarations: [
AppComponent,
LandingComponent,
DialogComponent,
LoadingSpinnerComponent,
DemoPipe
],
imports array in module
This content other modules which are required by the component. If we want to use Angular
reactive form this is the place where you need to import those. Not only inbuild modules you can
also import custom modules in here.
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule,
FontAwesomeModule,
ReactiveFormsModule,
FormsModule
],
providers array in module
This array contains the services which is required under that particular module. If we import
service to a module it will be available to all the components under that module. But we can
import service only just for a single component without importing to a module.
providers: [ApiCallService]
bootstrap array in module
This contains the entry component of the application. This only exists in the root module.
when we are creating an application it creates an app.module root module default.
bootstrap: [AppComponent]
exports array in module
This specifies declarations and modules which is available for a component in other
modules. If you have a module to share a few components with other different modules you can
use this array to export those before using them in the other modules.
exports: [ SelectDirective, DemoPipe, FormsModule ]
Component
The Angular Component is a class, which we decorate by @Component class decorator.
The Component controls the part of our user interface (or view). The Task List application listed
above has three components. The TaskComponent displays the list of Tasks. The
TaskAddComponent helps us to create new tasks. The rootComponent is the Parent component
of these components and only displays the application’s name.
The component, that we had created in the Create Your First Angular Application as shown
below
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'GettingStarted';
}
The Component has four important parts
1. Import Statement
2. Class
3. Template
4. Metadata
The Import statement imports the dependencies required by this component. The class contains
the application logic. The @Component class decorator decorates it.
Template
The Component needs a View to display. The Template defines that View.
The Template is just a subset of HTML that tells Angular how to display the view. It is a
standard HTML page using tags like h1, h2, etc. It also uses Angular-specific markup like {} (for
interpolation), [] (for Property binding), etc.
Metadata
Metadata tells angular how to Process the class.
We attach the Metadata to a class using a class decorator. When we attach @Component class
decorator to the class, then it becomes Component class.
The class decorator uses the configuration object, which provides Angular with the necessary
information to create the component. For Example, @Component directives come with
configuration options like selector, templateURL (or template), directives, etc
Data Binding
Angular uses the Data Binding to get the data from the Component to our View (Template). This
is done using the special HTML Angular-specific markup known as the Template Syntax.
The Angular supports four types of Data binding
1. Interpolation
Data is bound from component to View
2. Property Binding
Data is bound from the component to the property of an HTML control in the view like
3. Event Binding
The DOM Events are bound from View to a method in the Component
4. Two-way Binding/Model Binding
The data flow in both directions from view to component or from component to view
Template
A template looks like regular HTML, except that it also contains Angular template syntax, which
alters the HTML based on your application's logic and the state of application and DOM data.
Your template can use data binding to coordinate the application and DOM data, pipes to
transform data before it is displayed, and directives to apply application logic to what gets
displayed.
src/app/hero-list.component.html
<h2>Hero List</h2>
<p><em>Select a hero from the list to see details.</em></p>
<ul>
<li *ngFor="let hero of heroes">
<button type="button" (click)="selectHero(hero)">
{{hero.name}}
</button>
</li>
</ul>
<app-hero-detail *ngIf="selectedHero" [hero]="selectedHero"></app-hero-detail>
This template uses typical HTML elements like <h2> and <p>. It also includes Angular
template-syntax elements, *ngFor, {{hero.name}}, (click), [hero], and <app-hero-detail>. 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. See more about data binding below.
The <app-hero-detail> element tag in the example represents a new component,
HeroDetailComponent. The HeroDetailComponent defines the hero-detail portion of the
rendered DOM structure specified by the HeroListComponent component.
Component Communication:
What are components in Angular?
Components are the basic building blocks of Angular applications.
3 ways to communicate data between Angular components
Parent to Child: Sharing Data via Input
Child to Parent: Sharing Data via ViewChild with AfterViewInit
Child to Parent: Sharing Data via Output() and EventEmitter
1. Parent to Child: Sharing Data via Input
To share data from parent to child component via @Input Decorator.
@Input links a property of a child component with a value that was given by the parent
component.
For e.g :
Create 2 components parent.component.ts and child.component.ts
Let's create a simple string variable in our parent.component.ts file, It will contain the message
that we want to give to our child.
Add bellow code in parent.component.ts file :
import { Component } from '@angular/core';
@Component({
selector: 'app-parent',
template: `
<app-child [childMessage]="parentMessage"></app-child>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent{
parentMessage = "message from parent";
constructor() { }
}
Add bellow code in child.component.ts file :
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-child',
template: ` Say {{ message } `,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
@Input() childMessage: string;
constructor() { }
}
2. Child to Parent: Sharing Data via ViewChild with AfterViewInit
ViewChild allows a child component to be injected into a parent component.
It will give the parent access to its attributes and functions.
A Child won’t be available to give access until the view has been initialized.
This means we need to implement the AfterViewInit lifecycle hook to receive the data from the
child.
Add bellow code in parent.component.ts file :
import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { ChildComponent } from "../child/child.component";
@Component({
selector: 'app-parent',
template: `
Message: {{ message }}
<app-child></app-child>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent implements AfterViewInit {
@ViewChild(ChildComponent) child;
constructor() { }
Message:string;
ngAfterViewInit() {
this.message = this.child.message
}
}
Add bellow code in child.component.ts
import { Component} from '@angular/core';
@Component({
selector: 'app-child',
template: ` `,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
message = 'Hello Angular!';
constructor() { }
3. Child to Parent: Sharing Data via Output() and EventEmitter
Another way to share data is to emit data from the child component which can be listed by the
parent component.
This approach is ideal when you want to share data changes that occur on things like button
clicks, form entries, and other user events.
For e.g.
In the parent, we create a function to receive the message and set it equal to the message
variable.
In the child, we declare a messageEvent variable with the Output decorator and set it equal to a
new event emitter.
Then we create a function named sendMessage that calls emit on this event with the message we
want to send. Lastly, we create a button to trigger this function.
The parent can now subscribe to this messageEvent that’s outputted by the child component,
then run the receive message function whenever this event occurs.
Add bellow code in parent.component.ts file :
import { Component } from '@angular/core';
@Component({
selector: 'app-parent',
template: `
Message: {{message}}
<app-child (messageEvent)="receiveMessage($event)"></app-child>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent {
constructor() { }
Message:string;
receiveMessage($event) {
this.message = $event
}
}
Add bellow code in child.component.ts file :
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<button (click)="sendMessage()">Send Message</button>
`,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
message: string = "Hey Angular!"
@Output() messageEvent = new EventEmitter<string>();
constructor() { }
sendMessage() {
this.messageEvent.emit(this.message)
}
}
What are Services in Angular
In Angular, services are a way to share data and functionality across different parts of an
application. They are classes that can be injected into components and other services, and they
are used to encapsulate logic that is not specific to a particular component.
Services are a good way to organize and share code that is not directly related to the UI of your
application. They can be used to abstract away complex logic, such as calling a REST API or
performing calculations, and make it available to multiple components.
To create a service in Angular, you can use the @Injectable decorator to specify that the class
can be injected into other components and services. Then, you can use the @Injectable
decorator to specify the dependencies that the service requires.
Here’s an example of a simple service in Angular:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class MyService {
constructor() {}
getData() {
return 'some data';
}
}
The $http Service
The $http service is one of the most common used services in AngularJS applications. The
service makes a request to the server, and lets your application handle the response.
Example
Use the $http service to request data from the server:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
$http.get("welcome.htm").then(function (response) {
$scope.myWelcome = response.data;
});
});
Angular Forms
A Template driven form
A template-driven form is the most basic technique to create an Angular form. It creates and
manages the underlying form instance using Angular's two-way data binding directive.
Furthermore, a template form is primarily driven by the view component. As a result, it manages
the form via HTML directives rather than TypeScript. Because the construction of form controls
is outsourced to the defined directives, a template-driven form is asynchronous.
Form Setup
We make a basic form component with a basic form template and a simple component, just like
the user profile form component we started with in this section:
<div class="container">
<h2>User Profile</h2>
<form>
<div class="form-group">
<label for="firstname">FirstName</label><br />
<input type="text" name="firstname" class="form-control" />
</div>
<div class="form-group">
<label for="lastname">LastName</label><br />
<input type="text" name="lastname" class="form-control" />
</div>
<div class="form-group">
<label for="email">EmailID</label><br />
<input type="text" name="email" class="form-control" />
</div>
<button class="btn btn-primary" type="submit">Save</button>
</form>
</div>
Directives
The directives we need to construct template-driven forms in angular are in the FormsModule, so
import it and add it as an import to our NgModule.
import {FormsModule} from '@angular/forms';
@NgModule({
declarations: [UsersComponent, UserProfileComponent],
imports: [CommonModule, UsersRoutingModule, FormsModule],
})
export class UsersModule {}
One of the directives retrieved from the FormsModule is known as NgForm. This directive's
selector matches the <form> tag.
This ngForm object is hidden, but we can disclose it by attaching a local template reference
variable to the form element, as shown:
We can now use the variable userForm in our template to point to our ngForm directive object.
Two-Way Data Binding
The form module in Angular implements a directive with the [(ngModel)] selector, which allows
us to quickly perform data binding in two directions: from the view to the model and from the
model to the view.
[(...)] - Used for two-way binding Also known as banana-in-the-box as it looks like the same.
...
@Component({
selector: 'app-root',
template: `
<input type="text" [(ngModel)]="name">
<div>{{name}}</div>
`
})
class AppComponent {
name: string;
...
}
Here, we've connected [(ngModel)] with the name, so whatever changes we will do it will be
stored in the name variable.
We already know that the (eventName) syntax is used to connect to events generated by a certain
component.
On the other side, we use the [propertyName]= "foo" syntax to create one-way data binding by
setting the value of the property.
The [(ngModel)] syntax combines both to provide bidirectional data binding.
Domain Model
In Angular, we normally won't data bind to a simple string or object on our component but to a
domain model specified via a class or interface, such as User for our User Profile form.
export interface User {
firstName: string;
lastName: string;
email: string;
}
Now, create an object for the interface User:
userObj!: User;
constructor() {
this.userObj = {
firstName: ",
lastName: ",
email: ",
};
}
Now let's bind all our input controls to our userObj directly, like so:
<input [(ngModel)]="userObj.firstName">
<input [(ngModel)]="userObj.lastName">
...
Form Errors
In template-driven forms, we may handle two types of errors:
1. Handle form submission with ngSubmit and error handling in the submit function.
2. Add a feature that disables the submit button at first and enables it only after the form has
been validated.
Sub-Form Components
The FormGroup is a FormControl collection. It may also include additional FormGroups.
When we use the <form>, the ngForm directive constructs the top Level FormGroup behind the
scenes.
<form #userForm="ngForm" (ngSubmit)="save(userForm)">
...
</form>
Using the ngModelGroup directive, we can create a new FormGroup. Let us add the street, city,
and Pincode form control to the address FormGroup.
Simply wrap the fields within a div element with the ngModelGroup directive applied to it, as
seen below:
<div ngModelGroup="address">
<p>
<label for="city">City</label>
<input type="text" name="city" ngModel>
</p>
<p>
<label for="street">Street</label>
<input type="text" name="street" ngModel>
</p>
<p>
<label for="pincode">Pin Code</label>
<input type="text" name="pincode" ngModel>
</p>
</div>
Launch the app and submit it. The resulting item is seen below.
data : {
"firstname": "Foo",
"lastname": "Bar",
"email": "foobar@foobar"
"address": {
"city": "New York",
"street": "123 Street",
"pincode": "10001"
}
}
Validation
The validators in the model-driven method were defined via code in the component.
In the template-driven technique, validators are defined in our template through directives and
HTML5 properties. Let's add validators to our form template.
Except for the language, all of the fields were necessary, so we'll just add the required attribute to
those input fields.
<input
required
type= "text"
class= "form-control"
[(ngModel)]="userObj.firstName"
#firstName= "ngModel"
/>
Validation Styling
To provide visuals on the screen, we employ several Form Control States such as valid, touched,
and dirty. These are the FormControl properties.
However, with template-driven forms in angular, no FormControl object is created within the
component. So, to access FormControl, we may use one of the methods listed below.
1. Using .form property of ngForm
Using userForm.form.controls.firstName, we can get the title FormControl of userForm. We may
retrieve the control status of the FormControl using this object, as illustrated below.
<div class="form-group">
<label>FirstName</label>
<input type="text" class="form-control" name="firstName"
[(ngModel)]="userObj.firstName" required>
<div class="alert alert-info" role="alert">
<strong>Valid ? </strong>{{userForm.form.controls.firstName?.valid}} <br>
<strong>Invalid ? </strong>{{userForm.form.controls.firstName?.invalid}}<br>
<strong>Touched ? </strong>{{userForm.form.controls.firstName?.touched}}<br>
<strong>Untouched ?
</strong>{{userForm.form.controls.firstName?.untouched}}<br>
<strong>Dirty ? </strong>{{userForm.form.controls.firstName?.dirty}}<br>
<strong>Pristine ? </strong>{{userForm.form.controls.firstName?.pristine}}<br>
</div>
</div>
2. Using local template reference variable.
To access control state properties of title control, we need to go through
myForm.form.controls.title.valid. Using the ngModel directive, we can make this shorter.
As shown below, we are creating a local reference to the title FormControl using the ngModel
directive
<input type="text" class="form-control" name="firstName" [(ngModel)]="userObj.firstName"
required #firstName="ngModel">
Now, we can access the control state of the title using just firstName.valid, as shown below.
<div class="form-group">
<label>FirstName</label>
<input type="text" class="form-control" name="firstName"
[(ngModel)]="userObj.firstName" required firstName="ngModel">
<div class="alert alert-info" role="alert">
<strong>Valid ? </strong>{{firstName.valid}} <br>
<strong>Invalid ? </strong>{{firstName.invalid}}<br>
<strong>Touched ? </strong>{{firstName.touched}}<br>
<strong>Untouched ? </strong>{{firstName.untouched}}<br>
<strong>Dirty ? </strong>{{firstName.dirty}}<br>
<strong>Pristine ? </strong>{{firstName.pristine}}<br>
</div>
</div>
Both ways will give the same output.
Validation Messages
In terms of form validation messages, we may utilize them the same way as in model-driven
forms. We may use the same HTML in our template-driven forms as long as we name the local
reference variables the same as the form controls in the model-driven method, as seen below:
<div class="form-control-error-message"
*ngIf="firstName.errors && (firstName.dirty || email.touched)">
<p *ngIf=" firstName.errors.required">FirstName is required</p>
</div>
Submitting the Form
We may submit the form using the ngSubmit directive or on the Submit button's click event.
Either option is acceptable.
Let's add ngSubmit to the form:
user-profile.component.html
<form #userForm="ngForm" (ngSubmit)="save(userForm)">
...
<button type="submit" class="btn btn-primary"
[disabled]="userForm.invalid">Save</button>
</form>
Now, we will create one method inside the component.
user-profile.component.ts
import { Form } from '@angular/forms';
...
{
...
save(userData: Form) {
console.log(userData);
}
}
Resetting the Form
As with the template-driven form, we may reset the form. As seen below,
<button class="btn btn-default" (click)="userForm.reset()">Reset</button>