Angular Interview Questions - List
Angular Interview Questions - List
No. Questions
3 What is TypeScript?
9 What is a template?
10 What is a module?
13 What is metadata?
16 What is a service
20 What is the option to choose between inline and external template file?
24 What is interpolation?
No. Questions
40 What is RxJS?
41 What is subscribing?
42 What is an observable?
43 What is an observer?
45 What is multicasting?
57 What are the mapping rules between Angular component and custom element?
77 What is JIT?
78 What is AOT?
No. Questions
87 What is folding?
98 What is zone?
What are the differences between AngularJS and Angular with respect to
110
dependency injection?
163 What is the role of template compiler for prevention of XSS attacks?
171 How do you support server side XSS protection in Angular application?
226 What are the imported modules in CLI generated feature modules?
227 What are the differences between ngmodule and javascript module?
236 What are the different ways to remove duplicate service registration?
237 How does forRoot method helpful to avoid duplicate router instances?
246 What are the possible data change scenarios for change detection?
249 Which are the methods of NgZone used to control change detection?
259 What are the differences between reactive forms and template driven forms?
276
AngularJS Angular
document.body.innerHTML = greeter(user);
The main building blocks of an Angular application is shown in the below diagram
Now this directive extends HTML element behavior with a yellow background as below
Components are the most basic UI building block of an Angular app which formed a
tree of Angular components. These components are subset of directives. Unlike
directives, components always have a template and only one component can be
instantiated per an element in a template. Let's see a simple example of Angular
component
@Component ({
selector: 'my-app',
template: ` <div>
<h1>{{title}}</h1>
<div>Learn Angular6 with examples</div>
</div> `,
})
Component Directive
Only one component can be present per Many directives can be used per
DOM element DOM element
9. What is a template?
A template is a HTML view where you can display data by binding controls to
properties of an Angular component. You can store your component's template in one
of two places. You can define it inline using the template property, or you can define
the template in a separate HTML file and link to it in the component metadata using
the @Component decorator's templateUrl property.
@Component ({
selector: 'my-app',
template: '
<div>
<h1>{{title}}</h1>
<div>Learn Angular</div>
</div>
'
})
@Component ({
selector: 'my-app',
templateUrl: 'app/app.component.html'
})
Modules are logical boundaries in your application and the application is divided into
separate modules to separate the functionality of your application. Lets take an
example of app.module.ts root module declared with @NgModule decorator as below,
@NgModule ({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ],
providers: []
})
export class AppModule { }
i. ngOnChanges: When the value of a data bound property changes, then this
method is called.
ii. ngOnInit: This is called whenever the initialization of the directive/component after
Angular first displays the data-bound properties happens.
iii. ngDoCheck: This is for the detection and to act on changes that Angular can't or
won't detect on its own.
iv. ngAfterContentInit: This is called in response after Angular projects external
content into the component's view.
v. ngAfterContentChecked: This is called in response after Angular checks the
content projected into the component.
vi. ngAfterViewInit: This is called in response after Angular initializes the component's
views and child views.
vii. ngAfterViewChecked: This is called in response after Angular checks the
component's views and child views.
viii. ngOnDestroy: This is the cleanup phase just before Angular destroys the
directive/component.
Data binding is a core concept in Angular and allows to define communication between
a component and the DOM, making it very easy to define interactive applications
without worrying about pushing and pulling data. There are four forms of data
binding(divided as 3 categories) which differ in the way the data is flowing.
Interpolation: {{ value }}: Adds the value of a property from the component
<li>Name: {{ user.name }}</li>
<li>Address: {{ user.address }}</li>
ii. From the DOM to the Component: Event binding: (event)=”function”: When a
specific DOM event happens (eg.: click, change, keyup), call the specified method
in the component
<button (click)="logout()"></button>
Metadata is used to decorate a class so that it can configure the expected behavior of
the class. The metadata is represented by decorators
i. Class decorators, e.g. @Component and @NgModule
@Component({
selector: 'my-component',
template: '<div>Class decorator</div>',
})
export class MyComponent {
constructor() {
console.log('Hey I am a component!');
}
}
@NgModule({
imports: [],
declarations: [],
})
export class MyModule {
constructor() {
console.log('Hey I am a module!');
}
}
ii. Property decorators Used for properties inside classes, e.g. @Input and @Output
@Component({
selector: 'my-component',
template: '<div>Property decorator</div>'
})
iii. Method decorators Used for methods inside classes, e.g. @HostListener
@Component({
selector: 'my-component',
template: '<div>Method decorator</div>'
})
export class MyComponent {
@HostListener('click', ['$event'])
onHostClick(event: Event) {
// clicked, `event` available
}
}
iv. Parameter decorators Used for parameters inside class constructors, e.g. @Inject,
Optional
@Component({
selector: 'my-component',
template: '<div>Parameter decorator</div>'
})
export class MyComponent {
constructor(@Inject(MyService) myService) {
console.log(myService); // MyService
}
}
Below are the list of few commands, which will come handy while creating angular
projects
ii. Generating Components, Directives & Services: ng generate/g The different types
of commands would be,
TypeScript classes has a default method called constructor which is normally used for
the initialization purpose. Whereas ngOnInit method is specific to Angular, especially
used to define Angular bindings. Even though constructor getting called first, it is
preferred to move all of your Angular bindings to ngOnInit method. In order to use
ngOnInit, you need to implement OnInit interface as below,
ngOnInit(){
//called after the constructor and called after the first ngOnChanges()
}
}
fetchAll(){
return this.http.get('https://api.github.com/repositories');
}
}
Let's take a time observable which continuously updates the view for every 2 seconds
with the current time.
@Component({
selector: 'async-observable-pipe',
template: `<div><code>observable|async</code>:
Time: {{ time | async }}</div>`
})
export class AsyncObservablePipeComponent {
time = new Observable(observer =>
setInterval(() => observer.next(new Date().toString()), 2000)
);
}
20. What is the option to choose between inline and external template
file?
You can store your component's template in one of two places. You can define it inline
using the template property, or you can define the template in a separate HTML file
and link to it in the component metadata using the @Component decorator's
templateUrl property.
The choice between inline and separate HTML is a matter of taste, circumstances, and
organization policy. But normally we use inline template for small portion of code and
external template file for bigger views. By default, the Angular CLI generates
components with a template file. But you can override that with the below command,
We use Angular ngFor directive in the template to display each item in the list. For
example, here we iterate over list of users,
The user variable in the ngFor double-quoted instruction is a template input variable
Sometimes an app needs to display a view or a portion of a view only under specific
circumstances. The Angular ngIf directive inserts or removes an element based on a
truthy/falsy condition. Let's take an example to display a message if the user age is
more than 18,
<p *ngIf="user.age > 18">You are not eligible for student pass!</p>
Note: Angular isn't showing and hiding the message. It is adding and removing the
paragraph element from the DOM. That improves performance, especially in the larger
projects with many data bindings.
Angular recognizes the value as unsafe and automatically sanitizes it, which removes
the script tag but keeps safe content such as the text content of the script tag. This
way it eliminates the risk of script injection attacks. If you still use it then it will be
ignored and a warning appears in the browser console.
Let's take an example of innerHtml property binding which causes XSS vulnerability,
Interpolation is a special syntax that Angular converts into property binding. It’s a
convenient alternative to property binding. It is represented by double curly braces({{}}).
The text between the braces is often the name of a component property. Angular
replaces that name with the string value of the corresponding component property.
<h3>
{{title}}
<img src="{{url}}" style="height:30px">
</h3>
In the example above, Angular evaluates the title and url properties and fills in the
blanks, first displaying a bold application title and then a URL.
i. new
ii. increment and decrement operators, ++ and --
iii. operator assignment, such as += and -=
iv. the bitwise operators | and &
v. the template expression operators
View-to-source-
1. [(target)]="expression" 2.
to-view(Two- Two-way
bindon-target="expression"
way)
A pipe takes in data as input and transforms it to a desired output. For example, let us
take a pipe to transform a component's birthday property into a human-friendly date
using date pipe.
@Component({
selector: 'app-birthday',
template: `<p>Birthday is {{ birthday | date }}</p>`
})
export class BirthdayComponent {
birthday = new Date(1987, 6, 18); // June 18, 1987
}
A pipe can accept any number of optional parameters to fine-tune its output. The
parameterized pipe can be created by declaring the pipe name with a colon ( : ) and
then the parameter value. If the pipe accepts multiple parameters, separate the values
with colons. Let's take a birthday example with a particular format(dd/MM/yyyy):
@Component({
selector: 'app-birthday',
template: `<p>Birthday is {{ birthday | date:'dd/MM/yyyy'}}</p>` // 18/06/1
})
export class BirthdayComponent {
birthday = new Date(1987, 6, 18);
}
Note: The parameter value can be any valid template expression, such as a string literal
or a component property.
@Component({
selector: 'app-birthday',
template: `<p>Birthday is {{ birthday | date:'fullDate' | uppercase}}
})
export class BirthdayComponent {
birthday = new Date(1987, 6, 18);
}
Apart from built-inn pipes, you can write your own custom pipe with the below key
characteristics,
i. A pipe is a class decorated with pipe metadata @Pipe decorator, which you import
from the core Angular library For example,
@Pipe({name: 'myCustomPipe'})
ii. The pipe class implements the PipeTransform interface's transform method that
accepts an input value followed by optional parameters and returns the
transformed value. The structure of pipeTransform would be as below,
interface PipeTransform {
transform(value: any, ...args: any[]): any
}
iii. The @Pipe decorator allows you to define the pipe name that you'll use within
template expressions. It must be a valid JavaScript identifier.
@Pipe({name: 'customFileSizePipe'})
export class FileSizePipe implements PipeTransform {
transform(size: number, extension: string = 'MB'): string {
return (size / (1024 * 1024)).toFixed(2) + extension;
}
}
Now you can use the above pipe in template expression as below,
template: `
<h2>Find the size of a file</h2>
<p>Size: {{288966 | customFileSizePipe: 'GB'}}</p>
`
A pure pipe is only called when Angular detects a change in the value or the
parameters passed to a pipe. For example, any changes to a primitive input value
(String, Number, Boolean, Symbol) or a changed object reference (Date, Array, Function,
Object). An impure pipe is called for every change detection cycle no matter whether
the value or parameters changes. i.e, An impure pipe is called often, as often as every
keystroke or mouse-move.
Every application has at least one Angular module, the root module that you bootstrap
to launch the application is called as bootstrapping module. It is commonly known as
AppModule. The default structure of AppModule generated by AngularCLI would be as
follows,
```javascript
/* JavaScript imports */
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
Observables are declarative which provide support for passing messages between
publishers and subscribers in your application. They are mainly used for event handling,
asynchronous programming, and handling multiple values. In this case, you define a
function for publishing values, but it is not executed until a consumer subscribes to it.
The subscribed consumer then receives notifications until the function completes, or
until they unsubscribe.
Most of the Front-end applications communicate with backend services over HTTP
protocol using either XMLHttpRequest interface or the fetch() API. Angular provides a
simplified client HTTP API known as HttpClient which is based on top of
XMLHttpRequest interface. This client is avaialble from @angular/common/http package.
You can import in your root module as below,
Below are the steps need to be followed for the usage of HttpClient.
i. Import HttpClient into root module:
import { HttpClientModule } from '@angular/common/http';
@NgModule({
imports: [
BrowserModule,
// import HttpClientModule after BrowserModule.
HttpClientModule,
],
......
})
export class AppModule {}
@Injectable()
export class UserProfileService {
constructor(private http: HttpClient) { }
getUserProfile() {
return this.http.get(this.userProfileUrl);
}
}
iii. Create a component for subscribing service: Let's create a component called
UserProfileComponent(userprofile.component.ts) which inject UserProfileService
and invokes the service method,
fetchUserProfile() {
this.userProfileService.getUserProfile()
.subscribe((data: User) => this.user = {
id: data['userId'],
name: data['firstName'],
city: data['city']
});
}
Since the above service method returns an Observable which needs to be subscribed in
the component.
getUserResponse(): Observable<HttpResponse<User>> {
return this.http.get<User>(
this.userUrl, { observe: 'response' });
}
If the request fails on the server or failed to reach the server due to network issues then
HttpClient will return an error object instead of a successful reponse. In this case, you
need to handle in the component by passing error object as a second callback to
subscribe() method.
fetchUser() {
this.userService.getProfile()
.subscribe(
(data: User) => this.userProfile = { ...data }, // success path
error => this.error = error // error path
);
}
It is always a good idea to give the user some meaningful feedback instead of
displaying the raw error object returned from HttpClient.
For example, you can import observables and operators for using HttpClient as below,
// Execute with the observer object and Prints out each item
source.subscribe(myObserver);
// => Observer got a next value: 1
// => Observer got a next value: 2
// => Observer got a next value: 3
// => Observer got a next value: 4
// => Observer got a next value: 5
// => Observer got a complete notification
An Observable is a unique Object similar to a Promise that can help manage async
code. Observables are not part of the JavaScript language so we need to rely on a
popular Observable library called RxJS. The observables are created using new keyword.
interface Observer<T> {
closed?: boolean;
next: (value: T) => void;
error: (err: any) => void;
complete: () => void;
}
A handler that implements the Observer interface for receiving observable notifications
will be passed as a parameter for observable as below,
myObservable.subscribe(myObserver);
Note: If you don't supply a handler for a notification type, the observer ignores
notifications of that type.
Observable Promise
Execute
Declarative: Computation does not start until subscription so
immediately on
that they can be run whenever you need the result
creation
Push errors to
Subscribe method is used for error handling which makes
the child
centralized and predictable error handling
promises
You can handle errors by specifying an error callback on the observer instead of relying
on try/catch which are ineffective in asynchronous environment.
myObservable.subscribe({
next(num) { console.log('Next num: ' + num)},
error(err) { console.log('Received an errror: ' + err)}
});
The subscribe() method can accept callback function definitions in line, for next, error,
and complete handlers is known as short hand notation or Subscribe method with
positional arguments.
myObservable.subscribe(
x => console.log('Observer got a next value: ' + x),
err => console.error('Observer got an error: ' + err),
() => console.log('Observer got a complete notification')
);
The RxJS library also provides below utility functions for creating and working with
observables.
i. Converting existing code for async operations into observables
ii. Iterating through the values in a stream
iii. Mapping values to different types
iv. Filtering streams
v. Composing multiple streams
RxJS provides creation functions for the process of creating observables from things
such as promises, events, timers and Ajax requests. Let us explain each of them with an
example,
i. Create an observable from a promise
50. What will happen if you do not supply handler for observer?
Normally an observer object can define any combination of next, error and complete
notification type handlers. If you don't supply a handler for a notification type, the
observer just ignores notifications of that type.
Since Angular elements are packaged as custom elements the browser support of
angular elements is same as custom elements support.
This feature is is currently supported natively in a number of browsers and pending for
other browsers.
Custom elements (or Web Components) are a Web Platform feature which extends
HTML by allowing you to define a tag whose content is created and controlled by
JavaScript code. The browser maintains a CustomElementRegistry of defined custom
elements, which maps an instantiable JavaScript class to an HTML tag. Currently this
feature is supported by Chrome, Firefox, Opera, and Safari, and available in other
browsers through polyfills.
57. What
are the mapping rules between Angular component and
custom element?
The Component properties and logic maps directly into HTML attributes and the
browser's event system. Let us describe them in two steps,
i. The createCustomElement() API parses the component input properties with
corresponding attributes for the custom element. For example, component
@Input('myInputProp') converted as custom element attribute my-input-prop .
ii. The Component outputs are dispatched as HTML Custom Events, with the name of
the custom event matching the output name. For example, component @Output()
valueChanged = new EventEmitter() converted as custom element with dispatch
event as "valueChanged".
You can use the NgElement and WithProperties types exported from
@angular/elements.
Let's see how it can be applied by comparing with Angular component.
@Component(...)
class MyContainer {
@Input() message: string;
}
ii. After applying types typescript validates input value and their types,
You can use CLI command ng generate directive to create the directive class file. It
creates the source file( src/app/components/directivename.directive.ts ), the respective
test file(.spec.ts) and declare the directive class file in root module.
Let's take simple highlighter behavior as a example directive for DOM element. You can
create and apply the attribute directive using below steps,
i. Create HighlightDirective class with the file name
src/app/highlight.directive.ts . In this file, we need to import Directive from
core library to apply the metadata and ElementRef in the directive's constructor to
inject a reference to the host DOM element ,
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'red';
}
}
ii. Apply the attribute directive as an attribute to the host element(for example,
iii. Run the application to see the highlight behavior on paragraph element
ng serve
Angular Router is a mechanism in which navigation happens from one view to the next
as users perform application tasks. It borrows the concepts or model of browser's
application navigation.
<base href="/">
The RouterOutlet is a directive from the router library and it acts as a placeholder that
marks the spot in the template where the router should display the components for
that outlet. Router outlet is used like a component,
<router-outlet></router-outlet>
<!-- Routed components go here -->
The RouterLink is a directive on the anchor tags give the router control over those
elements. Since the navigation paths are fixed, you can assign string values to router-
link directive as below,
<h1>Angular Router</h1>
<nav>
<a routerLink="/todosList" >List of todos</a>
<a routerLink="/completed" >Completed todos</a>
</nav>
<router-outlet></router-outlet>
RouterLinkActive is a directive that toggles css classes for active RouterLink bindings
based on the current RouterState. i.e, The Router will add CSS classes when this link is
active and remove when the link is inactive. For example, you can add them to
RouterLinks as below.
<h1>Angular Router</h1>
<nav>
<a routerLink="/todosList" routerLinkActive="active">List of todos</a>
<a routerLink="/completed" routerLinkActive="active">Completed todos</a>
</nav>
<router-outlet></router-outlet>
69. What is router state?
RouterState is a tree of activated routes. Every node in this tree knows about the
"consumed" URL segments, the extracted parameters, and the resolved data. You can
access the current RouterState from anywhere in the application using the Router
service and the routerState property.
@Component({templateUrl:'template.html'})
class MyComponent {
constructor(router: Router) {
const state: RouterState = router.routerState;
const root: ActivatedRoute = state.root;
const child = root.firstChild;
const id: Observable<string> = child.params.map(p => p.id);
//...
}
}
i. NavigationStart,
ii. RouteConfigLoadStart,
iii. RouteConfigLoadEnd,
iv. RoutesRecognized,
v. GuardsCheckStart,
vi. ChildActivationStart,
vii. ActivationStart,
viii. GuardsCheckEnd,
ix. ResolveStart,
x. ResolveEnd,
xi. ActivationEnd
xii. ChildActivationEnd
xiii. NavigationEnd,
xiv. NavigationCancel,
xv. NavigationError
xvi. Scroll
71. What is activated route?
@Component({...})
class MyComponent {
constructor(route: ActivatedRoute) {
const id: Observable<string> = route.params.pipe(map(p => p.id));
const url: Observable<string> = route.url.pipe(map(segments => segments.join(
// route.data includes both `data` and `resolve`
const user = route.data.pipe(map(d => d.user));
}
}
A router must be configured with a list of route definitions. You configures the router
with routes via the RouterModule.forRoot() method, and adds the result to the
AppModule's imports array.
@NgModule({
imports: [
RouterModule.forRoot(
appRoutes,
{ enableTracing: true } // <-- debugging purposes only
)
// other imports here
],
...
})
export class AppModule { }
73. What is the purpose of Wildcard route?
If the URL doesn't match any predefined routes then it causes the router to throw an
error and crash the app. In this case, you can use wildcard route. A wildcard route has a
path consisting of two asterisks to match every URL.
For example, you can define PageNotFoundComponent for wildcard route as below
No, the Routing Module is a design choice. You can skip routing Module (for example,
AppRoutingModule) when the configuration is simple and merge the routing
configuration directly into the companion module (for example, AppModule). But it is
recommended when the configuration is complex and includes specialized guard and
resolver services.
Just-in-Time (JIT) is a type of compilation that compiles your app in the browser at
runtime. JIT compilation is the default when you run the ng build (build only) or ng
serve (build and serve locally) CLI commands. i.e, the below commands used for JIT
compilation,
ng build
ng serve
ng build --aot
ng serve --aot
Note: The ng build command with the --prod meta-flag ( ng build --prod ) compiles
with AOT by default.
The Angular components and templates cannot be understood by the browser directly.
Due to that Angular applications require a compilation process before they can run in a
browser. For example, In AOT compilation, both Angular HTML and TypeScript code
converted into efficient JavaScript code during the build phase before browser runs it.
@Component({
providers: [{
provide: MyService, useFactory: () => getService()
}]
})
function getService(){
return new MyService();
}
@Component({
providers: [{
provide: MyService, useFactory: getService
}]
})
If you still use arrow function, it generates an error node in place of the function. When
the compiler later interprets this node, it reports an error to turn the arrow function into
an exported function. Note: From Angular5 onwards, the compiler automatically
performs this rewriting while emitting the .js file.
86. Can I use any javascript feature for expression syntax in AOT?
No, the AOT collector understands a subset of (or limited) JavaScript features. If an
expression uses unsupported syntax, the collector writes an error node to the
.metadata.json file. Later point of time, the compiler reports an error if it needs that
piece of metadata to generate the application code.
@Component({
selector: 'app-root'
})
Remember that the compiler can’t fold everything. For example, spread operator on
arrays, objects created using new keywords and function calls.
@NgModule({
declarations: wrapInArray(TypicalComponent)
})
export class TypicalModule {}
@NgModule({
declarations: [TypicalComponent]
})
export class TypicalModule {}
i. Expression form not supported: Some of the language features outside of the
compiler's restricted expression syntax used in angular metadata can produce this
error. Let's see some of these examples,
// ERROR
let username: string; // neither exported nor initialized
@Component({
selector: 'my-component',
template: ... ,
providers: [
{ provide: User, useValue: username }
]
})
export class MyComponent {}
iii. Function calls are not supported: The compiler does not currently support
function expressions or lambda functions. For example, you cannot set a provider's
useFactory to an anonymous function or arrow function as below.
providers: [
{ provide: MyStrategy, useFactory: function() { ... } },
{ provide: OtherStrategy, useFactory: () => { ... } }
]
iv. Destructured variable or constant not supported: The compiler does not support
references to variables assigned by destructuring. For example, you cannot write
something like this:
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"experimentalDecorators": true,
...
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"preserveWhitespaces": true,
...
}
}
{
"compilerOptions": {
"experimentalDecorators": true,
...
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"preserveWhitespaces": true,
...
}
}
@Component({
selector: 'my-component',
template: '{{user.contacts.email}}'
})
class MyComponent {
user?: User;
}
You can disable binding expression type checking using $any() type cast function(by
surrounding the expression). In the following example, the error Property contacts does
not exist is suppressed by casting user to the any type.
template:
'{{ $any(user).contacts.email }}'
The $any() cast function also works with this to allow access to undeclared members of
the component.
template:
'{{ $any(this).contacts.email }}'
@Component({
selector: 'my-component',
template: '<span *ngIf="user"> {{user.name}} contacted through {{contact!.email
})
class MyComponent {
user?: User;
contact?: Contact;
The expression used in an ngIf directive is used to narrow type unions in the Angular
template compiler similar to if expression in typescript. So *ngIf allows the typeScript
compiler to infer that the data used in the binding expression will never be undefined.
@Component({
selector: 'my-component',
template: '<span *ngIf="user"> {{user.contact.email}} </span>'
})
class MyComponent {
user?: User;
}
i. Angular packages: Angular core and optional modules; their package names begin
@angular/.
ii. Support packages: Third-party libraries that must be present for Angular apps to
run.
iii. Polyfill packages: Polyfills plug gaps in a browser's JavaScript implementation.
ng new codelyzer
ng lint
You need to follow below steps to implement animation in your angular project,
@NgModule({
imports: [
BrowserModule,
BrowserAnimationsModule
],
declarations: [ ],
bootstrap: [ ]
})
export class AppModule { }
ii. Importing animation functions into component files: Import required animation
functions from @angular/animations in component files(for example,
src/app/app.component.ts).
import {
trigger,
state,
style,
animate,
transition,
// ...
} from '@angular/animations';
iii. Adding the animation metadata property: add a metadata property called
animations: within the @Component() decorator in component files(for example,
src/app/app.component.ts)
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.css'],
animations: [
// animation triggers go here
]
})
Angular's state() function is used to define different states to call at the end of each
transition. This function takes two arguments: a unique name like open or closed and a
style() function.
state('open', style({
height: '300px',
opacity: 0.5,
backgroundColor: 'blue'
})),
The style function is used to define a set of styles to associate with a given state name.
You need to use it along with state() function to set CSS style attributes. For example, in
the close state, the button has a height of 100 pixels, an opacity of 0.8, and a
background color of green.
state('close', style({
height: '100px',
opacity: 0.8,
backgroundColor: 'green'
})),
@Component({
selector: 'app-animate',
templateUrl: `<div [@changeState]="currentState" class="myblock mx-auto"></div>`,
styleUrls: `.myblock {
background-color: green;
width: 300px;
height: 250px;
border-radius: 5px;
margin: 5rem;
}`,
animations: [
trigger('changeState', [
state('state1', style({
backgroundColor: 'green',
transform: 'scale(1)'
})),
state('state2', style({
backgroundColor: 'red',
transform: 'scale(1.5)'
})),
transition('*=>state1', animate('300ms')),
transition('*=>state2', animate('2000ms'))
])
]
})
export class AnimateComponent implements OnInit {
@Input() currentState;
constructor() { }
ngOnInit() {
}
}
106. What is transition function?
The animation transition function is used to specify the changes that occur between
one state and another over a period of time. It accepts two arguments: the first
argument accepts an expression that defines the direction between two transition
states, and the second argument accepts an animate() function.
Let's take an example state transition from open to closed with an half second
transition between states.
AngularJS Angular
Dependency injection tokens are Tokens can have different types. They are often
always strings classes and sometimes can be strings.
i. You can enable ivy in a new project by using the --enable-ivy flag with the ng new
command
ii. You can add it to an existing project by adding enableIvy option in the
angularCompilerOptions in your project's tsconfig.app.json .
{
"compilerOptions": { ... },
"angularCompilerOptions": {
"enableIvy": true
}
}
Yes, it is a recommended configuration. Also, AOT compilation with Ivy is faster. So you
need set the default build options(with in angular.json) for your project to always use
AOT compilation.
{
"projects": {
"my-project": {
"architect": {
"build": {
"options": {
...
"aot": true,
}
}
}
}
}
}
After that add the following to the "compilerOptions" section of your project's
tsconfig.json
"plugins": [
{"name": "@angular/language-service"}
]
Note: The completion and diagnostic services works for .ts files only. You need to use
custom plugins for supporting HTML files.
ii. Error checking: It can also warn you of mistakes in your code.
iii. Navigation: Navigation allows you to hover a component, directive, module and
then click and press F12 to go directly to its definition.
118. How do you add web workers in your application?
You can add web worker anywhere in your application. For example, If the file that
contains your expensive computation is src/app/app.component.ts , you can add a Web
Worker using ng generate web-worker app command which will create
src/app/app.worker.ts web worker file. This command will perform below actions,
iii. The component app.component.ts file updated with web worker file
Note: You may need to refactor your initial scaffolding web worker code for sending
messages to and from.
You need to remember two important things when using Web Workers in Angular
projects,
In Angular8, the CLI Builder API is stable and available to developers who want to
customize the Angular CLI by adding or modifying commands. For example, you
could supply a builder to perform an entirely new task, or to change which third-party
tool is used by an existing command.
The Angular CLI command ng run is used to invoke a builder with a specific target
configuration. The workspace configuration file, angular.json , contains default
configurations for built-in builders.
An App shell is a way to render a portion of your application via a route at build time.
This is useful to first paint of your application that appears quickly because the browser
can render static HTML and CSS without the need to initialize JavaScript. You can
achieve this using Angular CLI which generates an app shell for running server-side of
your app.
i. @Component()
ii. @Directive()
iii. @Pipe()
iv. @Injectable()
v. @NgModule()
@Input() myProperty;
@Output() myEvent = new EventEmitter();
declarations: [
YourComponent,
YourPipe,
YourDirective
],
128. What are the restrictions on declarable classes?
A Subject is like an Observable, but can multicast to many Observers. Subjects are like
EventEmitters: they maintain a registry of many listeners.
import { Subject } from 'rxjs';
subject.subscribe({
next: (v) => console.log(`observerA: ${v}`)
});
subject.subscribe({
next: (v) => console.log(`observerB: ${v}`)
});
subject.next(1);
subject.next(2);
Bazel is a powerful build tool developed and massively used by Google and it can keep
track of the dependencies between different packages and build targets. In Angular8,
you can build your CLI application with Bazel. Note: The Angular framework itself is
built with Bazel.
i. It creates the possibility of building your back-ends and front-ends with the same
tool
ii. The incremental build and tests
iii. It creates the possibility to have remote builds and cache on a build farm.
The @angular/bazel package provides a builder that allows Angular CLI to use Bazel as
the build tool.
i. Use in an existing applciation: Add @angular/bazel using CLI
ng add @angular/bazel
ii. Use in a new application: Install the package and create the application with
collection option
bazel build [targets] // Compile the default output artifacts of the given
targets.
bazel test [targets] // Run the tests with *_test targets found in the
pattern.
bazel run [target]: Compile the program represented by target and then run it.
A platform is the context in which an Angular application runs. The most common
platform for Angular applications is a web browser, but it can also be an operating
system for a mobile device, or a web server. The runtime-platform is provided by the
@angular/platform-* packages and these packages allow applications that make use of
@angular/core and @angular/common to execute in different environments. i.e, Angular
can be used as platform-independent framework in different environments, For
example,
<input #uname>
and define view child directive and access it in ngAfterViewInit lifecycle hook
@ViewChild('uname') input;
ngAfterViewInit() {
console.log(this.input.nativeElement.value);
}
In Angular7, you can subscribe to router to detect the changes. The subscription for
router events would be as below,
@Component({
selector: 'app-root',
template: `<router-outlet></router-outlet>`
})
export class AppComponent {
(or)
let headers = new HttpHeaders().set('header1', headerValue1); // create header ob
headers = headers.append('header2', headerValue2); // add a new header, creating
headers = headers.append('header3', headerValue3); // add another header
i. The first build contains ES2015 syntax which takes the advantage of built-in
support in modern browsers, ships less polyfills, and results in a smaller bundle
size.
ii. The second build contains old ES5 syntax to support older browsers with all
necessary polyfills. But this results in a larger bundle size.
Note: This strategy is used to support multiple browsers but it only load the code that
the browser needs.
Yes, Angular 8 supports dynamic imports in router configuration. i.e, You can use the
import statement for lazy loading the module using loadChildren method and it will
be understood by the IDEs(VSCode and WebStorm), webpack, etc. Previously, you have
been written as below to lazily load the feature module. By mistake, if you have typo in
the module name it still accepts the string and throws an error during build time.
Lazy loading is one of the most useful concepts of Angular Routing. It helps us to
download the web pages in chunks instead of downloading everything in a big bundle.
It is used for lazy loading by asynchronously loading the feature module for routing
whenever required using the property loadChildren . Let's load both Customer and
Order feature modules lazily as below,
buildTarget.options.optimization = true;
addBuildTargetOption();
It supports the most recent two versions of all major browsers. The latest version of
Angular material is 8.1.1
@NgModule({
imports: [
// Other NgModule imports...
LocationUpgradeModule.config()
]
})
export class AppModule {}
Note: A chrome browser also opens and displays the test output in the "Jasmine HTML
Reporter".
i. Mandatory polyfills: These are installed automatically when you create your
project with ng new command and the respective import statements enabled in
'src/polyfills.ts' file.
ii. Optional polyfills: You need to install its npm package and then create import
statement in 'src/polyfills.ts' file. For example, first you need to install below npm
package for adding web animations (optional) polyfill. bash npm install --save
web-animations-js and create import statement in polyfill file. javascript import
'web-animations-js';
i. Angular 1:
Angular 1 (AngularJS) is the first angular framework released in the year 2010.
AngularJS is not built for mobile devices.
It is based on controllers with MVC architecture.
ii. Angular 2:
Angular 2 was released in the year 2016. Angular 2 is a complete rewrite of
Angular1 version.
The performance issues that Angular 1 version had has been addressed in
Angular 2 version.
Angular 2 is built from scratch for mobile devices unlike Angular 1 version.
Angular 2 is components based.
iii. Angular 3:
The following are the different package versions in Angular 2:
@angular/core v2.3.0
@angular/compiler v2.3.0
@angular/http v2.3.0
@angular/router v3.3.0
The router package is already versioned 3 so to avoid confusion switched to
Angular 4 version and skipped 3 version.
iv. Angular 4:
The compiler generated code file size in AOT mode is very much reduced.
With Angular 4 the production bundles size is reduced by hundreds of KB’s.
Animation features are removed from angular/core and formed as a separate
package.
Supports Typescript 2.1 and 2.2.
Angular Universal
New HttpClient
v. Angular 5:
Angular 5 makes angular faster. It improved the loading time and execution
time.
Shipped with new build optimizer.
Supports Typescript 2.5.
Service Worker
vi. Angular 6:
It is released in May 2018.
Includes Angular Command Line Interface (CLI), Component Development KIT
(CDK), Angular Material Package, Angular Elements.
Service Worker bug fixes.
i18n
Experimental mode for Ivy.
RxJS 6.0
Tree Shaking
vii. Angular 7:
It is released in October 2018.
TypeScript 3.1
RxJS 6.3
New Angular CLI
CLI Prompts capability provide an ability to ask questions to the user before
they run. It is like interactive dialog between the user and the CLI
With the improved CLI Prompts capability, it helps developers to make the
decision. New ng commands ask users for routing and CSS styles types(SCSS)
and ng add @angular/material asks for themes and gestures or animations.
viii. Angular 8:
It is released in May 2019.
TypeScript 3.4
ix. Angular 9:
It is released in February 2020.
TypeScript 3.7
Ivy enabled by default
x. Angular 10:
It is released in June 2020.
TypeScript 3.9
TSlib 2.0
Angular CLI provides it's installed version using below different ways using ng
command,
ng v
ng version
ng -v
ng --version
Angular supports most recent browsers which includes both desktop and mobile
browsers.
Browser Version
Chrome latest
Firefox latest
IE Mobile 11
In schematics world, it's a function that operates on a file tree to create, delete, or
modify files in a specific manner.
163. What is the role of template compiler for prevention of XSS attacks?
The offline template compiler prevents vulnerabilities caused by template injection, and
greatly improves application performance. So it is recommended to use offline
template compiler in production deployments without dynamically generating any
template.
The innerHtml is a property of HTML-Elements, which allows you to set it's html-
content programmatically. Let's display the below html code snippet in a <div> tag as
below using innerHTML binding,
<div [innerHTML]="htmlSnippet"></div>
Unfortunately this property could cause Cross Site Scripting (XSS) security bugs when
improperly handled.
<p>Interpolated value:</p>
<div >{{htmlSnippet}}</div>
<p>Binding of innerHTML:</p>
<div [innerHTML]="htmlSnippet"></div>
ii. Mark the trusted value by calling some of the below methods
a. bypassSecurityTrustHtml
b. bypassSecurityTrustScript
c. bypassSecurityTrustStyle
d. bypassSecurityTrustUrl
e. bypassSecurityTrustResourceUrl
Angular has built-in support for preventing http level vulnerabilities such as as cross-
site request forgery (CSRF or XSRF) and cross-site script inclusion (XSSI). Even though
these vulnerabilities need to be mitigated on server-side, Angular provides helpers to
make the integration easier on the client side.
interface HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>
}
You can use interceptors by declaring a service class that implements the intercept()
method of the HttpInterceptor interface.
@Injectable()
export class MyInterceptor implements HttpInterceptor {
constructor() {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any
...
}
}
i. Authentication
ii. Logging
iii. Caching
iv. Fake backend
v. URL transformation
vi. Modifying headers
Yes, Angular supports multiple interceptors at a time. You could define multiple
interceptors in providers property:
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: MyFirstInterceptor, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: MySecondInterceptor, multi: true }
],
The interceptors will be called in the order in which they were provided. i.e,
MyFirstInterceptor will be called first in the above interceptors configuration.
}
}
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, HttpClientModule],
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: MyInterceptor, multi: true }
],
bootstrap: [AppComponent]
})
export class AppModule {}
registerLocaleData(localeDe, 'de');
i. Mark static text messages in your component templates for translation: You can
place i18n on every element tag whose fixed text is to be translated. For example,
you need i18n attribue for heading as below,
ii. Create a translation file: Use the Angular CLI xi18n command to extract the
marked text into an industry-standard translation source file. i.e, Open terminal
window at the root of the app project and run the CLI command xi18n.
ng xi18n
The above command creates a file named messages.xlf in your project's root
directory.
Note: You can supply command options to change the format, the name, the
location, and the source locale of the extracted file.
iii. Edit the generated translation file: Translate the extracted text into the target
language. In this step, create a localization folder (such as locale )under root
directory(src) and then create target language translation file by copying and
renaming the default messages.xlf file. You need to copy source text node and
provide the translation under target tag. For example, create the translation
file(messages.de.xlf) for German language
For example, the translation file messages.de.xlf.html has generated trans-unit for
some text message as below
You can avoid this manual update of id attribute by specifying a custom id in the i18n
attribute by using the prefix @@.
For example, let's define same custom id myCustomId for two messages,
Since custom id is the same, both of the elements in the translation contain the same
text as below
<h2>Guten Morgen</h2>
<h2>Guten Morgen</h2>
Yes, you can achieve using <ng-container> attribute. Normally you need to wrap a text
content with i18n attribute for the translation. But if you don't want to create a new
DOM element just for the sake of translation, you can wrap the text in an element.
By the way, you can also assign meaning, description and id with the i18n-x="|@@"
syntax.
Let's take component binding with residenceStatus property which has "citizen",
"permanent resident" and "foreigner" possible values and the message maps those
values to the appropriate translations.
i. Error: It throws an error. If you are using AOT compilation, the build will fail. But if
you are using JIT compilation, the app will fail to load.
ii. Warning (default): It shows a 'Missing translation' warning in the console or shell.
iii. Ignore: It doesn't do anything.
If you use AOT compiler then you need to perform changes in configurations section
of your Angular CLI configuration file, angular.json.
"configurations": {
...
"de": {
...
"i18nMissingTranslation": "error"
}
}
If you use the JIT compiler, specify the warning level in the compiler config at bootstrap
by adding the 'MissingTranslationStrategy' property as below,
platformBrowserDynamic().bootstrapModule(AppModule, {
missingTranslation: MissingTranslationStrategy.Error,
providers: [
// ...
]
});
You can provide build configuration such as translation file path, name, format and
application url in configuration settings of Angular.json file. For example, the German
version of your application configured the build as follows,
"configurations": {
"de": {
"aot": true,
"outputPath": "dist/my-project-de/",
"baseHref": "/fr/",
"i18nFile": "src/locale/messages.de.xlf",
"i18nFormat": "xlf",
"i18nLocale": "de",
"i18nMissingTranslation": "error",
}
An Angular library is an Angular project that differs from an app in that it cannot run on
its own. It must be imported and used in an app. For example, you can import or add
service worker library to an Angular application which turns an application into a
Progressive Web App (PWA).
Note: You can create own third party library and publish it as npm package to be used
in an Application.
The AOT compiler is part of a build process that produces a small, fast, ready-to-run
application package, typically for production. It converts your Angular HTML and
TypeScript code into efficient JavaScript code during the build phase before the
browser downloads and runs that code.
constructor(myElement: ElementRef) {
el.nativeElement.style.backgroundColor = 'yellow';
}
TestBed is an api for writing unit tests for Angular applications and it's libraries. Even
though We still write our tests in Jasmine and run using Karma, this API provides an
easier way to create components, handle injection, test asynchronous behaviour and
interact with our application.
You can create your own schematic collections to integrate your library with the
Angular CLI. These collections are classified as 3 main schematics,
i. Install the dependency: At first, install the jquery dependency using npm
ii. Add the jquery script: In Angular-CLI project, add the relative path to jquery in the
angular.json file.
"scripts": [
"node_modules/jquery/dist/jquery.min.js"
]
iii. Start using jquery: Define the element in template. Whereas declare the jquery
variable and apply CSS classes on the element.
<div id="elementId">
<h1>JQuery integration</h1>
</div>
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
ngOnInit(): void {
$(document).ready(() => {
$('#elementId').css({'text-color': 'blue', 'font-size': '150%'});
});
}
}
@NgModule({
imports: [
BrowserModule,
HttpClientModule,
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
You can access the current RouterState from anywhere in the Angular app using the
Router service and the routerState property.
When you are creating your project with angular cli, you can use ng new command. It
generates all your components with predefined sass files.
But if you are changing your existing style in your project then use ng set command,
<div [hidden]="!user.name">
My name is: {{user.name}}
</div>
The main difference is that *ngIf will remove the element from the DOM, while [hidden]
actually plays with the CSS style by setting display:none . Generally it is expensive to
add and remove stuff from the DOM for frequent actions.
For example, you can provide 'hello' list based on a greeting array,
@Component({
selector: 'list-pipe',
template: `<ul>
<li *ngFor="let i of greeting | slice:0:5">{{i}}</li>
</ul>`
})
export class PipeListComponent {
greeting: string[] = ['h', 'e', 'l', 'l', 'o', 'm','o', 'r', 'n', 'i', 'n', 'g'
}
For example, you can capture the index in a variable named indexVar and displays it
with the todo's name using ngFor directive as below.
The main purpose of using *ngFor with trackBy option is performance optimization.
Normally if you use NgFor with large data sets, a small change to one item by removing
or adding an item, can trigger a cascade of DOM manipulations. In this case, Angular
sees only a fresh list of new object references and to replace the old DOM elements
with all new DOM elements. You can help Angular to track which items added or
removed by providing a trackBy function which takes the index and the current item
as arguments and needs to return the unique identifier for this item.
NgSwitch directive is similar to JavaScript switch statement which displays one element
from among several possible elements, based on a switch condition. In this case only
the selected element placed into the DOM. It has been used along with NgSwitch ,
NgSwitchCase and NgSwitchDefault directives.
For example, let's display the browser details based on selected browser using ngSwitch
directive.
<div [ngSwitch]="currentBrowser.name">
<chrome-browser *ngSwitchCase="'chrome'" [item]="currentBrowser"></chrome
<firefox-browser *ngSwitchCase="'firefox'" [item]="currentBrowser"></fire
<opera-browser *ngSwitchCase="'opera'" [item]="currentBrowser"></opera-bro
<safari-browser *ngSwitchCase="'safari'" [item]="currentBrowser"></safari
<ie-browser *ngSwitchDefault [item]="currentItem"></ie-browser>
</div>
ii. Aliasing with @Input()/@Output() decorator: The alias can be specified for the
property name by passing the alias name to the @Input()/@Output() decorator.i.e.
It will be in the form of @Input(alias) or @Output(alias).
The safe navigation operator(?)(or known as Elvis Operator) is used to guard against
null and undefined values in property paths when you are not aware whether a path
exists or not. i.e. It returns value of the object path if it exists, else it returns the null
value.
For example, you can access nested properties of a user profile easily without null
reference errors as below,
Using this safe navigation operator, Angular framework stops evaluating the expression
when it hits the first null value and renders the view without any errors.
You don't need any special configuration. In Angular9, the Ivy renderer is the default
Angular compiler. Even though Ivy is available Angular8 itself, you had to configure it in
tsconfig.json file as below,
i. Pipe operator
ii. Safe navigation operator
iii. Non-null assertion operator
The pipe operator has a higher precedence than the ternary operator (?:). For example,
the expression first ? second : third | fourth is parsed as first ? second : (third
| fourth) .
Basically, there are two main kinds of entry components which are following -
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent] // bootstrapped entry component need to be declared h
})
You can use ngDoBootstrap hook for a manual bootstrapping of the application instead
of using bootstrap array in @NgModule annotation. This hook is part of DoBootstap
interface.
interface DoBootstrap {
ngDoBootstrap(appRef: ApplicationRef): void
}
The module needs to be implement the above interface to use the hook for
bootstrapping.
216. Is
it necessary for bootstrapped component to be entry
component?
Yes, the bootstrapped component needs to be an entry component. This is because the
bootstrapping process is an imperative process.
217. What is a routed entry component?
Since router definition requires you to add the component in two places (router and
entryComponents), these components are always entry components.
Note: The compilers are smart enough to recognize a router definition and
automatically add the router component into entryComponents .
Most of the time, you don't need to explicity to set entry components in
entryComponents array of ngModule decorator. Because angular adds components
from both @NgModule.bootstrap and route definitions to entry components
automatically.
No, only the entry components and template components appears in production
builds. If a component isn't an entry component and isn't found in a template, the tree
shaker will throw it away. Due to this reason, make sure to add only true entry
components to reduce the bundle size.
The Angular compiler is used to convert the application code into JavaScript code. It
reads the template markup, combines it with the corresponding component class code,
and emits component factories which creates JavaScript representation of the
component along with elements of @Component metadata.
222. What is the role of ngModule metadata in compilation process?
The @NgModule metadata is used to tell the Angular compiler what components to be
compiled for this module and how to link this module with other modules.
The Angular compiler finds a component or directive in a template when it can match
the selector of that component or directive in that template. Whereas it finds a pipe if
the pipe's name appears within the pipe syntax of the template HTML.
The Angular core libraries and third-party libraries are available as NgModules.
Feature modules are NgModules, which are used for the purpose of organizing code.
The feature module can be created with Angular CLI using the below command in the
root directory,
Angular CLI creates a folder called my-custom-feature with a file inside called my-
custom-feature.module.ts with the following contents
@NgModule({
imports: [
CommonModule
],
declarations: []
})
export class MyCustomFeature { }
Note: The "Module" suffix shouldn't present in the name because the CLI appends it.
226. What are the imported modules in CLI generated feature modules?
In the CLI generated feature module, there are two JavaScript import statements at the
top of the file
227. What
are the differences between ngmodule and javascript
module?
Below are the main differences between Angular NgModule and javascript module,
There is no restriction
NgModule bounds declarable classes only
classes
Extend the entire application with services by Can't extend the application
adding providers to provides array with services
i. If you use a component without declaring it, Angular returns an error message.
ii. If you try to declare the same class in more than one module then compiler emits
an error.
i. Create the element(component, directive and pipes) and export it from the file
where you wrote it
ii. Import it into the appropriate module.
iii. Declare it in the @NgModule declarations array.
@Injectable({
providedIn: 'root', //Angular provide the service in root injector
})
export class MyService {
}
You should always provide your service in the root injector unless there is a case where
you want the service to be available only if you import a particular @NgModule.
234. How do you restrict provider scope to a module?
@Injectable({
providedIn: SomeModule,
})
export class SomeService {
}
@NgModule({
providers: [SomeService],
})
export class SomeModule {
}
i. Set the providedIn property of the @Injectable() to "root". This is the preferred
way(starting from Angular 6.0) of creating a singleton service since it makes your
services tree-shakable.
@Injectable({
providedIn: 'root',
})
export class MyService {
}
ii. Include the service in root module or in a module that is only imported by root
module. It has been used to register services before Angular 6.0.
@NgModule({
...
providers: [MyService],
...
})
i. Use the providedIn syntax instead of registering the service in the module.
ii. Separate your services into their own module.
iii. Define forRoot() and forChild() methods in the module.
The Shared Module is the module in which you put commonly used directives, pipes,
and components into one module that is shared(import it) throughout the application.
For example, the below shared module imports CommonModule, FormsModule for
common directives and components, pipes and directives based on the need,
@NgModule({
imports: [ CommonModule ],
declarations: [ UserComponent, NewUserDirective, OrdersPipe ],
exports: [ UserComponent, NewUserDirective, OrdersPipe,
CommonModule, FormsModule ]
})
export class SharedModule { }
No, it is not recommended to share services by importing module. i.e Import modules
when you want to use directives, pipes, and components only. The best approach to get
a hold of shared services is through 'Angular dependency injection' because importing
a module will result in a new service instance.
In Angular 9.1, the API method getLocaleDirection can be used to get the current
direction in your app. This method is useful to support Right to Left locales for your
Internationalization based applications.
...
constructor(@Inject(LOCALE_ID) locale) {
"scripts": {
"postinstall": "ngcc"
}
Angular provides a service called NgZone which creates a zone named angular to
automatically trigger change detection when the following conditions are satisfied.
/****************************************************************************
* Zone JS is required by default for Angular itself.
*/
// import 'zone.js/dist/zone'; // Included with Angular CLI.
246. What are the possible data update scenarios for change detection?
The change detection works in the following scenarios where the data changes needs
to update the application HTML.
@Component({
selector: 'app-event-listener',
template: `
<button (click)="onClick()">Click</button>
{{message}}`
})
export class EventListenerComponent {
message = '';
onClick() {
this.message = 'data updated';
}
}
iii. HTTP Data Request: You can get data from a server through an HTTP request
ngOnInit() {
this.httpClient.get(this.serverUrl).subscribe(response => {
this.data = response.data; // change detection will happen automaticall
});
}
iv. Macro tasks setTimeout() or setInterval(): You can update the data in the callback
function of setTimeout or setInterval
data = 'default value';
ngOnInit() {
setTimeout(() => {
this.data = 'data updated'; // Change detection will happen automatical
});
}
v. Micro tasks Promises: You can update the data in the callback function of promise
ngOnInit() {
Promise.resolve(1).then(v => {
this.data = v; // Change detection will happen automatically
});
}
vi. Async operations like Web sockets and Canvas: The data can be updated
asynchronously using WebSocket.onmessage() and Canvas.toBlob().
zone.run(() => {
// outside zone
expect(zoneThis).toBe(zone);
setTimeout(function() {
// the same outside zone exist here
expect(zoneThis).toBe(zone);
});
});
There are four lifecycle hooks for asynchronous operations from zone.js.
ii. onInvokeTask: This hook triggers when an asynchronous task is about to execute.
For example, when the callback of setTimeout() is about to execute.
iii. onHasTask: This hook triggers when the status of one kind of task inside a zone
changes from stable(no tasks in the zone) to unstable(a new task is scheduled in
the zone) or from unstable to stable.
iv. onInvoke: This hook triggers when a synchronous function is going to execute in
the zone.
Whereas runOutsideAngular() method is used when you don't want to trigger change
detection.
You can change the settings of zone by configuring them in a separate file and import it
just after zonejs import. For example, you can disable the requestAnimationFrame()
monkey patch to prevent change detection for no data update as one setting and
prevent DOM events(a mousemove or scroll event) to trigger change detection. Let's
say the new file named zone-flags.js,
/********************************************************************************
* Zone JS is required by default for Angular.
*/
import `./zone-flags`;
import 'zone.js/dist/zone'; // Included with Angular CLI.
content_copy
@Component({
selector: 'app-up-down',
animations: [
trigger('upDown', [
state('up', style({
height: '200px',
opacity: 1,
backgroundColor: 'yellow'
})),
state('down', style({
height: '100px',
opacity: 0.5,
backgroundColor: 'green'
})),
transition('up => down', [
animate('1s')
]),
transition('down => up', [
animate('0.5s')
]),
]),
],
templateUrl: 'up-down.component.html',
styleUrls: ['up-down.component.css']
})
export class UpDownComponent {
isUp = true;
toggle() {
this.isUp = !this.isUp;
}
You can configure injectors with providers at different levels of your application by
setting a metadata value. The configuration can happen in one of three places,
No. The @Injectable() decorator is not strictly required if the class has other Angular
decorators on it or does not have any dependencies. But the important thing here is
any class that is going to be injected with Angular is decorated. i.e, If we add the
decorator, the metadata design:paramtypes is added, and the dependency injection
can do it's job. That is the exact reason to add the @Injectable() decorator on a service
if this service has some dependencies itself. For example, Let's see the different
variations of AppService in a root component,
ii. The below AppService with dummy decorator and httpService can be injected in
AppComponent without any problems. This is because meta information is
generated with dummy decorator.
function SomeDummyDecorator() {
return (constructor: Function) => console.log(constructor);
}
@SomeDummyDecorator()
export class AppService {
constructor(http: HttpService) {
console.log(http);
}
}
and the generated javascript code of above service has meta information about
HttpService, js var AppService = (function () { function AppService(http) {
console.log(http); } AppService = __decorate([ core_1.Injectable(),
__metadata('design:paramtypes', [http_service_1.HttpService]) ], AppService);
return AppService; }()); exports.AppService = AppService; 3. The below AppService
with @injectable decorator and httpService can be injected in AppComponent without
any problems. This is because meta information is generated with Injectable decorator.
js @Injectable({ providedIn: 'root', }) export class AppService {
constructor(http: HttpService) { console.log(http); } }
i. Register the reactive forms module which declares reactive-form directives in your
app
@NgModule({
imports: [
// other imports ...
ReactiveFormsModule
],
})
export class AppModule { }
ii. Create a new FormControl instance and save it in the component.
@Component({
selector: 'user-profile',
styleUrls: ['./user-profile.component.css']
})
export class UserProfileComponent {
userName = new FormControl('');
}
<label>
User name:
<input type="text" [formControl]="userName">
</label>
Finally, the component with reactive form control appears as below, ```js import {
Component } from '@angular/core'; import { FormControl } from '@angular/forms';
@Component({
selector: 'user-profile',
styleUrls: ['./user-profile.component.css']
template: `
<label>
User name:
<input type="text" [formControl]="userName">
</label>
`
})
export class UserProfileComponent {
userName = new FormControl('');
}
```
ii. Bind the form from template to the component using ngModel syntax
iii. Attach NgForm directive to the tag in order to create FormControl instances and
register them
<form #registerForm="ngForm">
<label for="name">Name</label>
<input type="text" class="form-control" id="name"
required
[(ngModel)]="model.name" name="name"
#name="ngModel">
<div [hidden]="name.valid || name.pristine"
class="alert alert-danger">
Please enter your name
</div>
v. Let's submit the form with ngSubmit directive and add type="submit" button at
the bottom of the form to trigger form submit.
<form (ngSubmit)="onSubmit()" #heroForm="ngForm">
// Form goes here
<button type="submit" class="btn btn-success" [disabled]="!registerForm.form.
```html
<div class="container">
<h1>Registration Form</h1>
<form (ngSubmit)="onSubmit()" #registerForm="ngForm">
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name"
required
[(ngModel)]="model.name" name="name"
#name="ngModel">
<div [hidden]="name.valid || name.pristine"
class="alert alert-danger">
Please enter your name
</div>
</div>
<button type="submit" class="btn btn-success"
[disabled]="!registerForm.form.valid">Submit</button>
</form>
</div>
```
Form
Created(FormControl instance) in
model Created by directives
component explicitly
setup
Data
Synchronous Asynchronous
updates
Form
custom Defined as Functions Defined as Directives
validation
Feature Reactive Template-Driven
i. FormGroup: It defines a form with a fixed set of controls those can be managed
together in an one object. It has same properties and methods similar to a
FormControl instance. This FormGroup can be nested to create complex forms as
below.
@Component({
selector: 'user-profile',
templateUrl: './user-profile.component.html',
styleUrls: ['./user-profile.component.css']
})
export class UserProfileComponent {
userProfile = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl(''),
address: new FormGroup({
street: new FormControl(''),
city: new FormControl(''),
state: new FormControl(''),
zip: new FormControl('')
})
});
onSubmit() {
// Store this.userProfile.value in DB
}
}
<label>
First Name:
<input type="text" formControlName="firstName">
</label>
<label>
Last Name:
<input type="text" formControlName="lastName">
</label>
<div formGroupName="address">
<h3>Address</h3>
<label>
Street:
<input type="text" formControlName="street">
</label>
<label>
City:
<input type="text" formControlName="city">
</label>
<label>
State:
<input type="text" formControlName="state">
</label>
<label>
Zip Code:
<input type="text" formControlName="zip">
</label>
</div>
<button type="submit" [disabled]="!userProfile.valid">Submit</button>
</form>
ii. FormArray: It defines a dynamic form in an array format, where you can add and
remove controls at run time. This is useful for dynamic forms when you don’t know
how many controls will be present within the group.
@Component({
selector: 'order-form',
templateUrl: './order-form.component.html',
styleUrls: ['./order-form.component.css']
})
export class OrderFormComponent {
constructor () {
this.orderForm = new FormGroup({
firstName: new FormControl('John', Validators.minLength(3)),
lastName: new FormControl('Rodson'),
items: new FormArray([
new FormControl(null)
])
});
}
onSubmitForm () {
// Save the items this.orderForm.value in DB
}
onAddItem () {
this.orderForm.controls
.items.push(new FormControl(null));
}
onRemoveItem (index) {
this.orderForm.controls['items'].removeAt(index);
}
}
<label>
First Name:
<input type="text" formControlName="firstName">
</label>
<label>
Last Name:
<input type="text" formControlName="lastName">
</label>
<div>
<p>Add items</p>
<ul formArrayName="items">
<li *ngFor="let item of orderForm.controls.items.controls; let i = index"
<input type="text" formControlName="{{i}}">
<button type="button" title="Remove Item" (click)="onRemoveItem(i)">Rem
</li>
</ul>
<button type="button" (click)="onAddItem">
Add an item
</button>
</div>
updateProfile() {
this.userProfile.patchValue({
firstName: 'John',
address: {
street: '98 Crescent Street'
}
});
}
Note: Remember to update the properties against the exact model structure.
For example, the user profile component creation becomes easier as shown here.
{{diagnostic}}
<div class="form-group">
// FormControls goes here
</div>
onSubmit() {
if (this.myform.valid) {
console.log("Form is submitted");
// Perform business logic here
this.myform.reset();
}
}
Now, your form model resets the form back to its original pristine state.
266. What are the types of validator functions?
In reactive forms, the validators can be either synchronous or asynchronous functions,
i. Sync validators: These are the synchronous functions which take a control instance
and immediately return either a set of validation errors or null. Also, these
functions passed as second argument while instantiating the form control. The
main use cases are simple checks like whether a field is empty, whether it exceeds
a maximum length etc.
ii. Async validators: These are the asynchronous functions which take a control
instance and return a Promise or Observable that later emits a set of validation
errors or null. Also, these functions passed as second argument while instantiating
the form control. The main use cases are complex validations like hitting a server to
check the availability of a username or email.
this.myForm = formBuilder.group({
firstName: ['value'],
lastName: ['value', *Some Sync validation function*],
email: ['value', *Some validation function*, *Some asynchronous validation fu
});
Template parse errors: Can't have multiple template bindings on one element.
In this case, You need to use either ng-container or ng-template. Let's say if you try to
loop over the items only when the items are available, the below code throws an error
in the browser
<ng-container *ngIf="items">
<ul *ngFor="let item of items">
<li></li>
</ul>
</ng-container>
The :host pseudo-class selector is used to target styles in the element that hosts the
component. Since the host element is in a parent component's template, you can't
reach the host element from inside the component by other means. For example, you
can create a border for parent element as below,
//Other styles for app.component.css
//...
:host {
display: block;
border: 1px solid black;
padding: 20px;
}
In Angular, there is an url property of router package to get the current route. You
need to follow the below few steps,
console.log(this.router.url); // /routename
During compile time, Angular CLI will download and inline the fonts that your
application is using. This performance update speed up the first contentful paint(FCP)
and this feature is enabled by default in apps built with version 11.
Content projection is a pattern in which you insert, or project, the content you want to
use inside another component.
275. What is ng-content and its purpose?
The ng-content is used to insert the content dynamically inside the component that
helps to increase component reusability.