Latest angular features - 2019
In this story, we will peek at some of additions in recent angular versions. We will look into AOT, Service workers, Angular libraries, Angular elements and other features. We will start with Angular (4/5+) features and then look into Angular (6/7+) features.

NoValidate added to form elements with FormsModule (4+)
Angular adds novalidate attribute to form elements when FormsModule is included. This disables browser’s native form validation, it is useful as often custom validation is defined in Angular. To re-enable native forms behaviors, use ngNoForm or add ngNativeValidate
Support of else statement with ngIf directive (4+)
The else template is used to display a template when the expression has false value. The else binding points to a <ng-template> labeled #otherContent in below example and if show is false other text is displayed.
<div *ngIf="show; else otherContent">Text to show</div>
<ng-template #otherContent>Other text</ng-template> Support for email validator in <input> (4+)
Instead of writing pattern to validate email in input fields, there is email validator in angular, just add email or email = "true" in element.
<input type="email" name="email" ngModel email>AOT Compilation by default in angular production builds (5+)
Angular offers two ways to compile your application:
- Just-in-Time (JIT): compiles app in the browser at runtime — default with
ng-buildorng-serve - Ahead-of-Time (AOT): compiles app at build time — append
--aotflags tong-buildorng-servecli commands
By compiling doesn’t imply it is converting JavaScript to binary but it is compiling to JavaScript that can be directly executed in browser, e.g. components and templates are converted to executable JavaScript
The AOT compiling provides several benefits like faster rendering, fewer async requests (through inline html/css templates), smaller size, detect template errors earlier and better security.
With Angular (5+), the production builds (e.g. ng build --prod) are AOT compiled by default.
Service Workers (5+)
Angular now provides rich support for Progressive Web Apps (PWA) by configuring service workers using @angular/service-worker package. Adding service workers is as easy as executing below command:
ng add @angular/pwaIt adds @angular/service-worker package, register it in app module, include link to manifest.json in index.html file, add icon files and service worker configuration file called ngsw-config.json which has settings like caching behaviour. It enables service worker when project is built with production flag.
New Life Cycle events (5+): GuardsCheckStart and ChildActivationStart
New life cycle events are added to the router. These events can be used for showing spinner on a specific router outlet or to measure performance of guards and/or resolvers. The routing life cycle events fire in the following sequence:
GuardsCheckStart -> ChildActivationStart -> ActivationStart ->
GuardsCheckEnd -> ResolveStart -> ResolveEnd -> ActivationEnd ->
ChildActivationEndHere is sample example:
class SampleComponent {
constructor(public router: Router, spinner: Spinner) {
router.events.subscribe(e => {
if (e instanceof ChildActivationStart) {
spinner.start(e.route);
} else if (e instanceof ChildActivationEnd) {
spinner.end(e.route);
}
});
}
}Singleton Services (6+) using providedIn
The new preferred way to create a singleton services is to specify on the service that it should be provided in the application root. This is done by setting providedIn to root on the service's @Injectable decorator. It’s also possible to specify that a service should be provided in a particular @NgModule
import { Injectable } from '@angular/core';@Injectable({
providedIn: 'root',
})
export class WeatherService {
}
The services will be bundled only in modules where they are injected, thus enabling tree shaking.
Angular Libraries (6+)
The angular now makes it easy to generate and consume angular library.
There are 3 important steps:
- Generate Library
ng g library sampleLib2. Build Lib (for production use --prod flag)
ng build sampleLib3. Consume library
The library can be consumed by importing and declaring in app module:
Import:
import { SampleLibComponent } from 'sampleLib';Add in declaration:
declarations: [SampleLibComponent]Use like any other component:
<lib-sampleLib></lib-sampleLib>The lib is prefix is added by default, can be changed using -- prefix flag while generating library.
Note that the library is imported as if it was present in node_modules . Angular CLI first looks in your tsconfig paths, then in the node_modules folder, so same code can be used if library is published. Below is added in tsconfig.json by CLI when library is generated:
"paths": {
"sampleLib": ["dist/sample-lib"],
"sampleLib/*": ["dist/sample-lib/*"]
}Custom Elements (6+)
Elements are Angular components packaged as custom elements, a web standard for defining new HTML elements in a framework-agnostic way. The custom element extends HTML by allowing you to define a tag whose content is created and controlled by JavaScript code. Creating a custom element is simple and straightforward, and automatically connects component-defined view with change detection and data binding, mapping Angular functionality to the corresponding native HTML equivalents.
Angular provides the createCustomElement() function for this from @angular/elements . First create new project as usual, but note that custom prefix is required for custom elements:
ng new elementdemo --prefix customThen add @angular/elements using ng add :
ng add @angular/elementsAdd component (e.g.ng g c popupElement ) just like regular component and it can be used in index.html (outside of angular) like other html elements:
e.g. <popup-element message="Hello"></popup-element>
Also, define custom element in App Module:
export class AppModule {
constructor(private injector: Injector) {
customElements.define(
'popup-element',
createCustomElement(PopupElementComponent, { injector: this.injector })
);
}ngDoBootstrap() {}
}
and add the component in declarations and entryComponents of @NgModule in app module:
declarations: [AppComponent, PopupElementComponent],
entryComponents: [PopupElementComponent]That’s all need to be done. This works in all major browsers (except for latest chrome, for that change "target": "es5" to "target": "es2015" in tsconfig.json and add es2015 polyfill for browsers not supporting es2015).
Bundle Budgets (7+)
New projects are also now defaulted using Size Budget . The build system notifies when app is reaching size limits. Default is warnings at 2MB and errors at 5MB.
The budget is set in angular.json under project > [ProjectName] > architect > build > configurations >production. This feature is more of keeping check on app bundle size within team — to get it fixed as soon as it hits the budget.
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
}
]Note: To get Warning or error for budget, you need to run build for production. The type specifies which scripts to check for limit e.g. all, allScript, any, anyScript, bundle, initial.
ng build --prodDifferential Loading (8 +)
Differential loading is a process by which the browser chooses between modern or legacy JavaScript based on its own capabilities.
Part of Sample output below from the index.html file produced during a build using ng build. Each script tag has a type="module" or nomodule attribute. Browsers with native support for ES modules only load the scripts with the module type attribute and ignore scripts with the nomodule attribute. Legacy browsers only load the scripts with the nomodule attribute, and ignore the script tags with the module type that load ES modules. The modern bundle contains modern syntax, takes advantage of built-in support in modern browsers, ships less polyfills, and results in a smaller bundle size. The second bundle, includes the additional compiled code, all necessary polyfills, and results in a larger bundle size. This strategy allows you to continue to build your web application to support multiple browsers, but only load the necessary code that the browser needs
<script src="main-es2015.js" type="module"></script>
<script src="main-es5.js" nomodule></script>The modern bundle contains modern syntax, takes advantage of built-in support in modern browsers, ships less polyfills, and results in a smaller bundle size. The second bundle, includes the additional compiled code, all necessary polyfills, and results in a larger bundle size. This strategy allows you to continue to build your web application to support multiple browsers, but only load the necessary code that the browser needs
Thanks for reading, feel free to share and tap on clap button 👏, if you enjoyed it 🎉.
