×

Welcome to Knowledge Base!

KB at your finger tips

This is one stop global knowledge base where you can learn about all the products, solutions and support features.

Categories
All
Web-Angular
Angular - Attribute directives

Attribute directives link

Change the appearance or behavior of DOM elements and Angular components with attribute directives.

See the live example / download example for a working example containing the code snippets in this guide.

Building an attribute directive link

This section walks you through creating a highlight directive that sets the background color of the host element to yellow.

  1. To create a directive, use the CLI command ng generate directive .

          
          ng generate directive highlight
        

    The CLI creates src/app/highlight.directive.ts , a corresponding test file src/app/highlight.directive.spec.ts , and declares the directive class in the AppModule .

    The CLI generates the default src/app/highlight.directive.ts as follows:

    src/app/highlight.directive.ts
          
          import { Directive } from '@angular/core';
    
    @Directive({
      selector: '[appHighlight]'
    })
    export class HighlightDirective {
    
    }
        

    The @Directive() decorator's configuration property specifies the directive's CSS attribute selector, [appHighlight] .

  2. Import ElementRef from @angular/core . ElementRef grants direct access to the host DOM element through its nativeElement property.

  3. Add ElementRef in the directive's constructor() to inject a reference to the host DOM element, the element to which you apply appHighlight .

  4. Add logic to the HighlightDirective class that sets the background to yellow.

    src/app/highlight.directive.ts
          
          import { Directive, ElementRef } from '@angular/core';
    
    @Directive({
      selector: '[appHighlight]'
    })
    export class HighlightDirective {
        constructor(private el: ElementRef) {
           this.el.nativeElement.style.backgroundColor = 'yellow';
        }
    }
        

Directives do not support namespaces.

src/app/app.component.avoid.html (unsupported)
      
      <p app:Highlight>This is invalid</p>
    

Applying an attribute directive link

  1. To use the HighlightDirective , add a <p> element to the HTML template with the directive as an attribute.

    src/app/app.component.html
          
          <p appHighlight>Highlight me!</p>
        

Angular creates an instance of the HighlightDirective class and injects a reference to the <p> element into the directive's constructor, which sets the <p> element's background style to yellow.

Handling user events link

This section shows you how to detect when a user mouses into or out of the element and to respond by setting or clearing the highlight color.

  1. Import HostListener from '@angular/core'.

    src/app/highlight.directive.ts (imports)
          
          import { Directive, ElementRef, HostListener } from '@angular/core';
        
  2. Add two event handlers that respond when the mouse enters or leaves, each with the @HostListener() decorator.

    src/app/highlight.directive.ts (mouse-methods)
          
          @HostListener('mouseenter') onMouseEnter() {
      this.highlight('yellow');
    }
    
    @HostListener('mouseleave') onMouseLeave() {
      this.highlight('');
    }
    
    private highlight(color: string) {
      this.el.nativeElement.style.backgroundColor = color;
    }
        

Subscribe to events of the DOM element that hosts an attribute directive, the <p> in this case, with the @HostListener() decorator.

The handlers delegate to a helper method, highlight() , that sets the color on the host DOM element, el .

The complete directive is as follows:

src/app/highlight.directive.ts
      
      @Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {

  constructor(private el: ElementRef) { }

  @HostListener('mouseenter') onMouseEnter() {
    this.highlight('yellow');
  }

  @HostListener('mouseleave') onMouseLeave() {
    this.highlight('');
  }

  private highlight(color: string) {
    this.el.nativeElement.style.backgroundColor = color;
  }

}
    

The background color appears when the pointer hovers over the paragraph element and disappears as the pointer moves out.

Passing values into an attribute directive link

This section walks you through setting the highlight color while applying the HighlightDirective .

  1. In highlight.directive.ts , import Input from @angular/core .

    src/app/highlight.directive.ts (imports)
          
          import { Directive, ElementRef, HostListener, Input } from '@angular/core';
        
  2. Add an appHighlight @Input() property.

    src/app/highlight.directive.ts
          
          @Input() appHighlight = '';
        

    The @Input() decorator adds metadata to the class that makes the directive's appHighlight property available for binding.

  3. In app.component.ts , add a color property to the AppComponent .

    src/app/app.component.ts (class)
          
          export class AppComponent {
      color = 'yellow';
    }
        
  4. To simultaneously apply the directive and the color, use property binding with the appHighlight directive selector, setting it equal to color .

    src/app/app.component.html (color)
          
          <p [appHighlight]="color">Highlight me!</p>
        

    The [appHighlight] attribute binding performs two tasks:

    • Applies the highlighting directive to the <p> element
    • Sets the directive's highlight color with a property binding

Setting the value with user input link

This section guides you through adding radio buttons to bind your color choice to the appHighlight directive.

  1. Add markup to app.component.html for choosing a color as follows:

    src/app/app.component.html (v2)
          
          <h1>My First Attribute Directive</h1>
    
    <h2>Pick a highlight color</h2>
    <div>
      <input type="radio" name="colors" (click)="color='lightgreen'">Green
      <input type="radio" name="colors" (click)="color='yellow'">Yellow
      <input type="radio" name="colors" (click)="color='cyan'">Cyan
    </div>
    <p [appHighlight]="color">Highlight me!</p>
        
  2. Revise the AppComponent.color so that it has no initial value.

    src/app/app.component.ts (class)
          
          export class AppComponent {
      color = '';
    }
        
  3. In highlight.directive.ts , revise onMouseEnter method so that it first tries to highlight with appHighlight and falls back to red if appHighlight is undefined .

    src/app/highlight.directive.ts (mouse-enter)
          
          @HostListener('mouseenter') onMouseEnter() {
      this.highlight(this.appHighlight || 'red');
    }
        
  4. Serve your application to verify that the user can choose the color with the radio buttons.

Binding to a second property link

This section guides you through configuring your application so the developer can set the default color.

  1. Add a second Input() property to HighlightDirective called defaultColor .

    src/app/highlight.directive.ts (defaultColor)
          
          @Input() defaultColor = '';
        
  2. Revise the directive's onMouseEnter so that it first tries to highlight with the appHighlight , then with the defaultColor , and falls back to red if both properties are undefined .

    src/app/highlight.directive.ts (mouse-enter)
          
          @HostListener('mouseenter') onMouseEnter() {
      this.highlight(this.appHighlight || this.defaultColor || 'red');
    }
        
  3. To bind to the AppComponent.color and fall back to "violet" as the default color, add the following HTML. In this case, the defaultColor binding doesn't use square brackets, [] , because it is static.

    src/app/app.component.html (defaultColor)
          
          <p [appHighlight]="color" defaultColor="violet">
      Highlight me too!
    </p>
        

    As with components, you can add multiple directive property bindings to a host element.

The default color is red if there is no default color binding. When the user chooses a color the selected color becomes the active highlight color.

Deactivating Angular processing with NgNonBindable link

To prevent expression evaluation in the browser, add ngNonBindable to the host element. ngNonBindable deactivates interpolation, directives, and binding in templates.

In the following example, the expression {{ 1 + 1 }} renders just as it does in your code editor, and does not display 2 .

src/app/app.component.html
      
      <p>Use ngNonBindable to stop evaluation.</p>
<p ngNonBindable>This should not evaluate: {{ 1 + 1 }}</p>
    

Applying ngNonBindable to an element stops binding for that element's child elements. However, ngNonBindable still lets directives work on the element where you apply ngNonBindable . In the following example, the appHighlight directive is still active but Angular does not evaluate the expression {{ 1 + 1 }} .

src/app/app.component.html
      
      <h3>ngNonBindable with a directive</h3>
<div ngNonBindable [appHighlight]="'yellow'">This should not evaluate: {{ 1 +1 }}, but will highlight yellow.
</div>
    

If you apply ngNonBindable to a parent element, Angular disables interpolation and binding of any sort, such as property binding or event binding, for the element's children.

Last reviewed on Mon Feb 28 2022
Angular - Understanding binding

Understanding binding link

In an Angular template, a binding creates a live connection between a part of the UI created from a template (a DOM element, directive, or component) and the model (the component instance to which the template belongs). This connection can be used to synchronize the view with the model, to notify the model when an event or user action takes place in the view, or both. Angular's Change Detection algorithm is responsible for keeping the view and the model in sync.

Examples of binding include:

  • text interpolations
  • property binding
  • event binding
  • two-way binding

Bindings always have two parts: a target which will receive the bound value, and a template expression which produces a value from the model.

Syntax link

Template expressions are similar to JavaScript expressions. Many JavaScript expressions are legal template expressions, with the following exceptions.

You can't use JavaScript expressions that have or promote side effects, including:

  • Assignments ( = , += , -= , ... )
  • Operators such as new , typeof , or instanceof
  • Chaining expressions with ; or ,
  • The increment and decrement operators ++ and --
  • Some of the ES2015+ operators

Other notable differences from JavaScript syntax include:

  • No support for the bitwise operators such as | and &
  • New template expression operators, such as |

Expression context link

Interpolated expressions have a context—a particular part of the application to which the expression belongs. Typically, this context is the component instance.

In the following snippet, the expression recommended and the expression itemImageUrl2 refer to properties of the AppComponent .

src/app/app.component.html
      
      <h4>{{recommended}}</h4>
<img alt="item 2" [src]="itemImageUrl2">
    

An expression can also refer to properties of the template's context such as a template input variable or a template reference variable.

The following example uses a template input variable of customer .

src/app/app.component.html (template input variable)
      
      <ul>
  <li *ngFor="let customer of customers">{{customer.name}}</li>
</ul>
    

This next example features a template reference variable, #customerInput .

src/app/app.component.html (template reference variable)
      
      <label>Type something:
  <input #customerInput>{{customerInput.value}}
</label>
    

Template expressions cannot refer to anything in the global namespace, except undefined . They can't refer to window or document . Additionally, they can't call console.log() or Math.max() and are restricted to referencing members of the expression context.

Preventing name collisions link

The context against which an expression evaluates is the union of the template variables, the directive's context object—if it has one—and the component's members. If you reference a name that belongs to more than one of these namespaces, Angular applies the following precedence logic to determine the context:

  1. The template variable name.
  2. A name in the directive's context.
  3. The component's member names.

To avoid variables shadowing variables in another context, keep variable names unique. In the following example, the AppComponent template greets the customer , Padma.

An ngFor then lists each customer in the customers array.

src/app/app.component.ts
      
      @Component({
  template: `
    <div>
      <!-- Hello, Padma -->
      <h1>Hello, {{customer}}</h1>
      <ul>
        <!-- Ebony and Chiho in a list-->
        <li *ngFor="let customer of customers">{{ customer.value }}</li>
      </ul>
    </div>
  `
})
class AppComponent {
  customers = [{value: 'Ebony'}, {value: 'Chiho'}];
  customer = 'Padma';
}
    

The customer within the ngFor is in the context of an <ng-template> and so refers to the customer in the customers array, in this case Ebony and Chiho. This list does not feature Padma because customer outside of the ngFor is in a different context. Conversely, customer in the <h1> doesn't include Ebony or Chiho because the context for this customer is the class and the class value for customer is Padma.

Expression best practices link

When using a template expression, follow these best practices:

  • Use short expressions

Use property names or method calls whenever possible. Keep application and business logic in the component, where it is accessible to develop and test.

  • Quick execution

Angular executes a template expression after every change detection cycle. Many asynchronous activities trigger change detection cycles, such as promise resolutions, HTTP results, timer events, key presses, and mouse moves.

An expression should finish quickly to keep the user experience as efficient as possible, especially on slower devices. Consider caching values when their computation requires greater resources.

No visible side effects link

According to Angular's unidirectional data flow model, a template expression should not change any application state other than the value of the target property. Reading a component value should not change some other displayed value. The view should be stable throughout a single rendering pass.

Idempotent expressions reduce side effects

An idempotent expression is free of side effects and improves Angular's change detection performance. In Angular terms, an idempotent expression always returns exactly the same thing until one of its dependent values changes.

Dependent values should not change during a single turn of the event loop. If an idempotent expression returns a string or a number, it returns the same string or number if you call it twice consecutively. If the expression returns an object, including an array , it returns the same object reference if you call it twice consecutively.

What's next link

  • Property binding
  • Event binding
Last reviewed on Thu May 12 2022
Read article
Angular - Binding syntax

Binding syntax link

Data binding automatically keeps your page up-to-date based on your application's state. You use data binding to specify things such as the source of an image, the state of a button, or data for a particular user.

See the live example / download example for a working example containing the code snippets in this guide.

Data binding and HTML link

Developers can customize HTML by specifying attributes with string values. In the following example, class , src , and disabled modify the <div> , <img> , and <button> elements respectively.

      
      <div class="special">Plain old HTML</div>
<img src="images/item.png">
<button disabled>Save</button>
    

Use data binding to control things like the state of a button:

src/app/app.component.html
      
      <!-- Bind button disabled state to `isUnchanged` property -->
<button type="button" [disabled]="isUnchanged">Save</button>
    

Notice that the binding is to the disabled property of the button's DOM element, not the attribute. Data binding works with properties of DOM elements, components, and directives, not HTML attributes.

HTML attributes and DOM properties link

Angular binding distinguishes between HTML attributes and DOM properties.

Attributes initialize DOM properties and you can configure them to modify an element's behavior. Properties are features of DOM nodes.

  • A few HTML attributes have 1:1 mapping to properties; for example,

          
          id
        
  • Some HTML attributes don't have corresponding properties; for example,

          
          aria-*
        
  • Some DOM properties don't have corresponding attributes; for example,

          
          textContent
        

Remember that HTML attributes and DOM properties are different things, even when they have the same name.

In Angular, the only role of HTML attributes is to initialize element and directive state.

When you write a data binding, you're dealing exclusively with the DOM properties and events of the target object.

Example 1: an <input> link

When the browser renders <input type="text" value="Sarah"> , it creates a corresponding DOM node with a value property and initializes that value to "Sarah".

      
      <input type="text" value="Sarah">
    

When the user enters Sally into the <input> , the DOM element value property becomes Sally . However, if you look at the HTML attribute value using input.getAttribute('value') , you can see that the attribute remains unchanged —it returns "Sarah".

The HTML attribute value specifies the initial value; the DOM value property is the current value.

To see attributes versus DOM properties in a functioning app, see the live example / download example especially for binding syntax.

Example 2: a disabled button link

A button's disabled property is false by default so the button is enabled.

When you add the disabled attribute, you are initializing the button's disabled property to true which disables the button.

      
      <button disabled>Test Button</button>
    

Adding and removing the disabled attribute disables and enables the button. However, the value of the attribute is irrelevant, which is why you cannot enable a button by writing <button disabled="false">Still Disabled</button> .

To control the state of the button, set the disabled property instead.

Property and attribute comparison link

Though you could technically set the [attr.disabled] attribute binding, the values are different in that the property binding must be a boolean value, while its corresponding attribute binding relies on whether the value is null or not. Consider the following:

      
      <input [disabled]="condition ? true : false">
<input [attr.disabled]="condition ? 'disabled' : null">
    

The first line, which uses the disabled property, uses a boolean value. The second line, which uses the disabled attribute checks for null .

Generally, use property binding over attribute binding as a boolean value is easy to read, the syntax is shorter, and a property is more performant.

To see the disabled button example in a functioning application, see the live example / download example . This example shows you how to toggle the disabled property from the component.

Types of data binding link

Angular provides three categories of data binding according to the direction of data flow:

  • From source to view
  • From view to source
  • In a two-way sequence of view to source to view
Type Syntax Category
Interpolation
Property
Attribute
Class
Style
      
      {{expression}} 
[target]="expression"
    
One-way from data source to view target
Event
      
      (target)="statement"
    
One-way from view target to data source
Two-way
      
      [(target)]="expression"
    
Two-way

Binding types other than interpolation have a target name to the left of the equal sign. The target of a binding is a property or event, which you surround with square bracket ( [ ] ) characters, parenthesis ( ( ) ) characters, or both ( [( )] ) characters.

The binding punctuation of [] , () , [()] , and the prefix specify the direction of data flow.

  • Use [] to bind from source to view
  • Use () to bind from view to source
  • Use [()] to bind in a two-way sequence of view to source to view

Place the expression or statement to the right of the equal sign within double quote ( "" ) characters. For more information see Interpolation and Template statements.

Binding types and targets link

The target of a data binding can be a property, an event, or an attribute name. Every public member of a source directive is automatically available for binding in a template expression or statement. The following table summarizes the targets for the different binding types.

Type Target Examples
Property Element property
Component property
Directive property
alt , src , hero , and ngClass in the following:
      
      <img [alt]="hero.name" [src]="heroImageUrl">
<app-hero-detail [hero]="currentHero"></app-hero-detail>
<div [ngClass]="{'special': isSpecial}"></div>
    
Event Elementevent
Component event
Directive event
click , deleteRequest , and myClick in the following:
      
      <button type="button" (click)="onSave()">Save</button>
<app-hero-detail (deleteRequest)="deleteHero()"></app-hero-detail>
<div (myClick)="clicked=$event" clickable>click me</div>
    
Two-way Event and property
      
      <input [(ngModel)]="name">
    
Attribute Attribute (the exception)
      
      <button type="button" [attr.aria-label]="help">help</button>
    
Class class property
      
      <div [class.special]="isSpecial">Special</div>
    
Style style property
      
      <button type="button" [style.color]="isSpecial ? 'red' : 'green'">
    
Last reviewed on Mon Feb 28 2022
Read article
Angular - Launching your app with a root module

Launching your app with a root module link

Prerequisites link

A basic understanding of the following:

  • JavaScript Modules vs. NgModules

An NgModule describes how the application parts fit together. Every application has at least one Angular module, the root module, which must be present for bootstrapping the application on launch. By convention and by default, this NgModule is named AppModule .

When you use the Angular CLI command ng new to generate an app, the default AppModule looks like the following:

      
      /* JavaScript imports */
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

/* the AppModule class with the @NgModule decorator */
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
    

After the import statements is a class with the @NgModule decorator.

The @NgModule decorator identifies AppModule as an NgModule class. @NgModule takes a metadata object that tells Angular how to compile and launch the application.

metadata object Details
declarations This application's lone component.
imports Import BrowserModule to have browser-specific services such as DOM rendering, sanitization, and location.
providers The service providers.
bootstrap The root component that Angular creates and inserts into the index.html host web page.

The default application created by the Angular CLI only has one component, AppComponent , so it is in both the declarations and the bootstrap arrays.

The declarations array link

The module's declarations array tells Angular which components belong to that module. As you create more components, add them to declarations .

You must declare every component in exactly one NgModule class. If you use a component without declaring it, Angular returns an error message.

The declarations array only takes declarables. Declarables are components, directives, and pipes. All of a module's declarables must be in the declarations array. Declarables must belong to exactly one module. The compiler emits an error if you try to declare the same class in more than one module.

These declared classes are visible within the module but invisible to components in a different module, unless they are exported from this module and the other module imports this one.

An example of what goes into a declarations array follows:

      
      declarations: [
  YourComponent,
  YourPipe,
  YourDirective
],
    

A declarable can only belong to one module, so only declare it in one @NgModule . When you need it elsewhere, import the module that contains the declarable you need.

Using directives with @NgModule link

Use the declarations array for directives. To use a directive, component, or pipe in a module, you must do a few things:

  1. Export it from the file where you wrote it.
  2. Import it into the appropriate module.
  3. Declare it in the @NgModule declarations array.

Those three steps look like the following. In the file where you create your directive, export it. The following example, named ItemDirective is the default directive structure that the CLI generates in its own file, item.directive.ts :

src/app/item.directive.ts
      
      import { Directive } from '@angular/core';

@Directive({
  selector: '[appItem]'
})
export class ItemDirective {
// code goes here
  constructor() { }

}
    

The key point here is that you have to export it, so that you can import it elsewhere. Next, import it into the NgModule , in this example app.module.ts , with a JavaScript import statement:

src/app/app.module.ts
      
      import { ItemDirective } from './item.directive';
    

And in the same file, add it to the @NgModule declarations array:

src/app/app.module.ts
      
      declarations: [
  AppComponent,
  ItemDirective
],
    

Now you could use your ItemDirective in a component. This example uses AppModule , but you'd do it the same way for a feature module. For more about directives, see Attribute Directives and Structural Directives. You'd also use the same technique for pipes and components.

Remember, components, directives, and pipes belong to one module only. You only need to declare them once in your application because you share them by importing the necessary modules. This saves you time and helps keep your application lean.

The imports array link

The module's imports array appears exclusively in the @NgModule metadata object. It tells Angular about other NgModules that this particular module needs to function properly.

src/app/app.module.ts (excerpt)
      
      imports: [
  BrowserModule,
  FormsModule,
  HttpClientModule
],
    

This list of modules are those that export components, directives, or pipes that component templates in this module reference. In this case, the component is AppComponent , which references components, directives, or pipes in BrowserModule , FormsModule , or HttpClientModule . A component template can reference another component, directive, or pipe when the referenced class is declared in this module, or the class was imported from another module.

The providers array link

The providers array is where you list the services the application needs. When you list services here, they are available app-wide. You can scope them when using feature modules and lazy loading. For more information, see Providers.

The bootstrap array link

The application launches by bootstrapping the root AppModule , which is also referred to as an entryComponent . Among other things, the bootstrapping process creates the component(s) listed in the bootstrap array and inserts each one into the browser DOM.

Each bootstrapped component is the base of its own tree of components. Inserting a bootstrapped component usually triggers a cascade of component creations that fill out that tree.

While you can put more than one component tree on a host web page, most applications have only one component tree and bootstrap a single root component.

This one root component is usually called AppComponent and is in the root module's bootstrap array.

In a situation where you want to bootstrap a component based on an API response, or you want to mount the AppComponent in a different DOM node that doesn't match the component selector, please refer to ApplicationRef.bootstrap() documentation.

More about Angular Modules link

For more on NgModules you're likely to see frequently in applications, see Frequently Used Modules.

Last reviewed on Mon Feb 28 2022
Read article
Angular - Browser support

Browser support link

Angular supports most recent browsers. This includes the following specific versions:

Browser Supported versions
Chrome latest
Firefox latest and extended support release (ESR)
Edge 2 most recent major versions
Safari 2 most recent major versions
iOS 2 most recent major versions
Android 2 most recent major versions

Angular's continuous integration process runs unit tests of the framework on all of these browsers for every pull request, using Sauce Labs.

Polyfills link

Angular is built on the latest standards of the web platform. Targeting such a wide range of browsers is challenging because they do not support all features of modern browsers. You compensate by loading polyfill scripts ("polyfills") for the browsers that you must support. See instructions on how to include polyfills into your project below.

The suggested polyfills are the ones that run full Angular applications. You might need additional polyfills to support features not covered by this list.

NOTE :
Polyfills cannot magically transform an old, slow browser into a modern, fast one.

Enabling polyfills with CLI projects link

The Angular CLI provides support for polyfills. If you are not using the CLI to create your projects, see Polyfill instructions for non-CLI users.

The polyfills options of the browser and test builder can be a full path for a file (Example: src/polyfills.ts ) or, relative to the current workspace or module specifier (Example: zone.js ).

If you create a TypeScript file, make sure to include it in the files property of your tsconfig file.

      
      {
  "extends": "./tsconfig.json",
  "compilerOptions": {
    ...
  },
  "files": [
    "src/main.ts",
    "src/polyfills.ts"
  ]
  ...
}
    

Polyfills for non-CLI users link

If you are not using the CLI, add your polyfill scripts directly to the host web page ( index.html ).

For example:

src/index.html
      
      <!-- pre-zone polyfills -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script>
  /**
   * you can configure some zone flags which can disable zone interception for some
   * asynchronous activities to improve startup performance - use these options only
   * if you know what you are doing as it could result in hard to trace down bugs.
   */
  // __Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
  // __Zone_disable_on_property = true; // disable patch onProperty such as onclick
  // __zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
  /*
   * in Edge developer tools, the addEventListener will also be wrapped by zone.js
   * with the following flag, it will bypass `zone.js` patch for Edge.
   */
  // __Zone_enable_cross_context_check = true;
</script>
<!-- zone.js required by Angular -->
<script src="node_modules/zone.js/bundles/zone.umd.js"></script>
<!-- application polyfills -->
    
Last reviewed on Fri Nov 04 2022
Read article
Angular - Building and serving Angular apps

Building and serving Angular apps link

This page discusses build-specific configuration options for Angular projects.

Configuring application environments link

You can define different named build configurations for your project, such as staging and production , with different defaults.

Each named configuration can have defaults for any of the options that apply to the various builder targets, such as build , serve , and test . The Angular CLI build , serve , and test commands can then replace files with appropriate versions for your intended target environment.

Configure environment-specific defaults link

A project's src/environments/ folder contains the base configuration file, environment.ts , which provides a default environment. You can add override defaults for additional environments, such as production and staging, in target-specific configuration files.

For example:

myProject/src/environments
environment.ts
environment.prod.ts
environment.staging.ts

The base file environment.ts , contains the default environment settings. For example:

      
      export const environment = {
  production: false
};
    

The build command uses this as the build target when no environment is specified. You can add further variables, either as additional properties on the environment object, or as separate objects. For example, the following adds a default for a variable to the default environment:

      
      export const environment = {
  production: false,
  apiUrl: 'http://my-api-url'
};
    

You can add target-specific configuration files, such as environment.prod.ts . The following content sets default values for the production build target:

      
      export const environment = {
  production: true,
  apiUrl: 'http://my-prod-url'
};
    

Using environment-specific variables in your app link

The following application structure configures build targets for production and staging environments:

src
app
app.component.html
app.component.ts
environments
environment.ts
environment.prod.ts
environment.staging.ts

To use the environment configurations you have defined, your components must import the original environments file:

      
      import { environment } from './../environments/environment';
    

This ensures that the build and serve commands can find the configurations for specific build targets.

The following code in the component file ( app.component.ts ) uses an environment variable defined in the configuration files.

      
      import { Component } from '@angular/core';
import { environment } from './../environments/environment';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  constructor() {
    console.log(environment.production); // Logs false for default environment
  }
  title = 'app works!';
}
    

Configure target-specific file replacements link

The main CLI configuration file, angular.json , contains a fileReplacements section in the configuration for each build target, which lets you replace any file in the TypeScript program with a target-specific version of that file. This is useful for including target-specific code or variables in a build that targets a specific environment, such as production or staging.

By default no files are replaced. You can add file replacements for specific build targets. For example:

      
      "configurations": {
  "production": {
    "fileReplacements": [
      {
        "replace": "src/environments/environment.ts",
        "with": "src/environments/environment.prod.ts"
      }
    ],
    
    

This means that when you build your production configuration with ng build --configuration production , the src/environments/environment.ts file is replaced with the target-specific version of the file, src/environments/environment.prod.ts .

You can add additional configurations as required. To add a staging environment, create a copy of src/environments/environment.ts called src/environments/environment.staging.ts , then add a staging configuration to angular.json :

      
      "configurations": {
  "production": {  },
  "staging": {
    "fileReplacements": [
      {
        "replace": "src/environments/environment.ts",
        "with": "src/environments/environment.staging.ts"
      }
    ]
  }
}
    

You can add more configuration options to this target environment as well. Any option that your build supports can be overridden in a build target configuration.

To build using the staging configuration, run the following command:

      
      ng build --configuration=staging
    

You can also configure the serve command to use the targeted build configuration if you add it to the "serve:configurations" section of angular.json :

      
      "serve": {
  "builder": "@angular-devkit/build-angular:dev-server",
  "options": {
    "browserTarget": "your-project-name:build"
  },
  "configurations": {
    "production": {
      "browserTarget": "your-project-name:build:production"
    },
    "staging": {
      "browserTarget": "your-project-name:build:staging"
    }
  }
},
    

Configuring size budgets link

As applications grow in functionality, they also grow in size. The CLI lets you set size thresholds in your configuration to ensure that parts of your application stay within size boundaries that you define.

Define your size boundaries in the CLI configuration file, angular.json , in a budgets section for each configured environment.

      
      {
  
  "configurations": {
    "production": {
      
      "budgets": []
    }
  }
}
    

You can specify size budgets for the entire app, and for particular parts. Each budget entry configures a budget of a given type. Specify size values in the following formats:

Size value Details
123 or 123b Size in bytes.
123kb Size in kilobytes.
123mb Size in megabytes.
12% Percentage of size relative to baseline. (Not valid for baseline values.)

When you configure a budget, the build system warns or reports an error when a given part of the application reaches or exceeds a boundary size that you set.

Each budget entry is a JSON object with the following properties:

Property Value
type The type of budget. One of:
Value Details
bundle The size of a specific bundle.
initial The size of JavaScript needed for bootstrapping the application. Defaults to warning at 500kb and erroring at 1mb.
allScript The size of all scripts.
all The size of the entire application.
anyComponentStyle This size of any one component stylesheet. Defaults to warning at 2kb and erroring at 4kb.
anyScript The size of any one script.
any The size of any file.
name The name of the bundle (for type=bundle ).
baseline The baseline size for comparison.
maximumWarning The maximum threshold for warning relative to the baseline.
maximumError The maximum threshold for error relative to the baseline.
minimumWarning The minimum threshold for warning relative to the baseline.
minimumError The minimum threshold for error relative to the baseline.
warning The threshold for warning relative to the baseline (min & max).
error The threshold for error relative to the baseline (min & max).

Configuring CommonJS dependencies link

It is recommended that you avoid depending on CommonJS modules in your Angular applications. Depending on CommonJS modules can prevent bundlers and minifiers from optimizing your application, which results in larger bundle sizes. Instead, it is recommended that you use ECMAScript modules in your entire application. For more information, see How CommonJS is making your bundles larger.

The Angular CLI outputs warnings if it detects that your browser application depends on CommonJS modules. To disable these warnings, add the CommonJS module name to allowedCommonJsDependencies option in the build options located in angular.json file.

      
      "build": {
  "builder": "@angular-devkit/build-angular:browser",
  "options": {
     "allowedCommonJsDependencies": [
        "lodash"
     ]
     
   }
   
},
    

Configuring browser compatibility link

The Angular CLI uses Browserslist to ensure compatibility with different browser versions. Autoprefixer is used for CSS vendor prefixing and @babel/preset-env for JavaScript syntax transformations.

Internally, the Angular CLI uses the below browserslist configuration which matches the browsers that are supported by Angular.

      
      last 1 Chrome version
last 1 Firefox version
last 2 Edge major versions
last 2 Safari major versions
last 2 iOS major versions
Firefox ESR
    

To override the internal configuration, add a new file named .browserslistrc , to the project directory, that specifies the browsers you want to support:

      
      last 1 Chrome version
last 1 Firefox version
    

See the browserslist repository for more examples of how to target specific browsers and versions.

Use browsersl.ist to display compatible browsers for a browserslist query.

Proxying to a backend server link

Use the proxying support in the webpack development server to divert certain URLs to a backend server, by passing a file to the --proxy-config build option. For example, to divert all calls for http://localhost:4200/api to a server running on http://localhost:3000/api , take the following steps.

  1. Create a file proxy.conf.json in your project's src/ folder.

  2. Add the following content to the new proxy file:

          
          {
      "/api": {
        "target": "http://localhost:3000",
        "secure": false
      }
    }
        
  3. In the CLI configuration file, angular.json , add the proxyConfig option to the serve target:

          
          
    "architect": {
      "serve": {
        "builder": "@angular-devkit/build-angular:dev-server",
        "options": {
          "browserTarget": "your-application-name:build",
          "proxyConfig": "src/proxy.conf.json"
        },
    
        
  4. To run the development server with this proxy configuration, call ng serve .

Edit the proxy configuration file to add configuration options; following are some examples. For a description of all options, see webpack DevServer documentation.

NOTE :
If you edit the proxy configuration file, you must relaunch the ng serve process to make your changes effective.

Rewrite the URL path link

The pathRewrite proxy configuration option lets you rewrite the URL path at run time. For example, specify the following pathRewrite value to the proxy configuration to remove "api" from the end of a path.

      
      {
  "/api": {
    "target": "http://localhost:3000",
    "secure": false,
    "pathRewrite": {
      "^/api": ""
    }
  }
}
    

If you need to access a backend that is not on localhost , set the changeOrigin option as well. For example:

      
      {
  "/api": {
    "target": "http://npmjs.org",
    "secure": false,
    "pathRewrite": {
      "^/api": ""
    },
    "changeOrigin": true
  }
}
    

To help determine whether your proxy is working as intended, set the logLevel option. For example:

      
      {
  "/api": {
    "target": "http://localhost:3000",
    "secure": false,
    "pathRewrite": {
      "^/api": ""
    },
    "logLevel": "debug"
  }
}
    

Proxy log levels are info (the default), debug , warn , error , and silent .

Proxy multiple entries link

You can proxy multiple entries to the same target by defining the configuration in JavaScript.

Set the proxy configuration file to proxy.conf.js (instead of proxy.conf.json ), and specify configuration files as in the following example.

      
      const PROXY_CONFIG = [
    {
        context: [
            "/my",
            "/many",
            "/endpoints",
            "/i",
            "/need",
            "/to",
            "/proxy"
        ],
        target: "http://localhost:3000",
        secure: false
    }
]

module.exports = PROXY_CONFIG;
    

In the CLI configuration file, angular.json , point to the JavaScript proxy configuration file:

      
      
"architect": {
  "serve": {
    "builder": "@angular-devkit/build-angular:dev-server",
    "options": {
      "browserTarget": "your-application-name:build",
      "proxyConfig": "src/proxy.conf.js"
    },

    

Bypass the proxy link

If you need to optionally bypass the proxy, or dynamically change the request before it's sent, add the bypass option, as shown in this JavaScript example.

      
      const PROXY_CONFIG = {
    "/api/proxy": {
        "target": "http://localhost:3000",
        "secure": false,
        "bypass": function (req, res, proxyOptions) {
            if (req.headers.accept.indexOf("html") !== -1) {
                console.log("Skipping proxy for browser request.");
                return "/index.html";
            }
            req.headers["X-Custom-Header"] = "yes";
        }
    }
}

module.exports = PROXY_CONFIG;
    

Using corporate proxy link

If you work behind a corporate proxy, the backend cannot directly proxy calls to any URL outside your local network. In this case, you can configure the backend proxy to redirect calls through your corporate proxy using an agent:

      
      npm install --save-dev https-proxy-agent
    

When you define an environment variable http_proxy or HTTP_PROXY , an agent is automatically added to pass calls through your corporate proxy when running npm start .

Use the following content in the JavaScript configuration file.

      
      var HttpsProxyAgent = require('https-proxy-agent');
var proxyConfig = [{
  context: '/api',
  target: 'http://your-remote-server.com:3000',
  secure: false
}];

function setupForCorporateProxy(proxyConfig) {
  var proxyServer = process.env.http_proxy || process.env.HTTP_PROXY;
  if (proxyServer) {
    var agent = new HttpsProxyAgent(proxyServer);
    console.log('Using corporate proxy server: ' + proxyServer);
    proxyConfig.forEach(function(entry) {
      entry.agent = agent;
    });
  }
  return proxyConfig;
}

module.exports = setupForCorporateProxy(proxyConfig);
    
Last reviewed on Mon Oct 24 2022
Read article

Still Thinking?
Give us a try!

We embrace agility in everything we do.
Our onboarding process is both simple and meaningful.
We can't wait to welcome you on AiDOOS!