Top 7 Angular Tips and Tricks

Top 7 Angular Tips and Tricks

Angular comes with so many features, both popular and unknown, the easiest way to discover tricks to achieve difficult tasks using Angular is to use Angular a lot more and learn in the process. Here are my favorite Angular tips and tricks.

Angular is a JavaScript framework for building web applications, especially single page applications. As a framework, it offers the best practices and tooling to easily develop these web applications. When building with Angular, you’ll be using declarative templates, dependency injection, etc. to power applications that can run on all platforms (web, mobile and desktop).

Angular already outlines its best practices for easy development using the framework, but there might be other tips that you’ve missed that will most likely make development easier or help your application run and load faster. So here are seven tips and tricks to making Angular applications better.

1. Use Services to Handle Side Effects

When building your application, it is always useful to reduce side effects like HTTP requests, time-based events, etc. Abstracting these from the component to services will help reduce the complexity of the component and also ensures the reusability of the service. An example would be fetching data from an external server. You could fetch data within your component like this:

    import { Component } from "@angular/core";
    
    @Component({
      selector: 'app-component',
      template: '<ul> <li *ngFor="let item of items">{{item}}</li> </ul>',
    })
    export class AppComponent implements OnInit{
      constructor(private http: HttpClient){
      }
      items = [];
      
      getItems(){
        return this.http.get('http://server.com/items')
      }
      
      ngOnInit(){
        this.getItems.subscribe(items => this.items = items);
      }
    }

This method used in fetching the items is local to the component and can’t be reused, and if items are being fetched in other components, this whole procedure will be repeated and that’s not very DRY. If multiple network requests are made, the component will be littered with these methods. Let’s refactor this component to use a service for external requests.

    @Injectable({
      providedIn: 'root'
    })
    export class ItemService {
      constructor (private http: HttpClient) {}
    
      getItems() {
        return this.http.get('http://server.com/items');
      }
    }

Then we’ll make use of it in the component:

    import { Component } from "@angular/core";
    
    @Component({
      selector: 'app-component',
      template: '<ul> <li *ngFor="let item of items">{{item}}</li> </ul>',
    })
    export class AppComponent implements OnInit{
      constructor(private itemsService: ItemsService){
      }
      items = [];
      
      ngOnInit(){
        this.itemsServices.getItems().subscribe(items => this.items = items);
      }
    }

This service can be used to fetch items application-wide.

2. ng add

This utility, introduced in Angular version 6, can be used to add a published package to your work environment, and it’ll run schematics in the background to update the functionality of your application. When downloading a package using this command, it also installs extra dependencies it needs to run, like polyfills, etc. Your application can be converted to a progressive web application using service workers and providing offline functionality using the command.

You can implement progressive web application features in your application by running the following command:

 ng add @angular/pwa 

Or if you wish to add a touch of Material Design in your application, you can add the Angular Material library

 ng add @angular/material 
3. Web Components

From Angular version 6 onward, you can develop custom native elements that can be used outside Angular. This can be done using a package introduced by Angular called Angular Elements (@angular/elements). This package provides a way to createCustomElements and polyfills to support browsers that aren’t compatible with web components. With this package, you can package your favourite components and use them within other frameworks like React, Vue, etc.

To get started building custom native elements in Angular, install the Angular Elements package in your application using the following command:

    ng add @angular/elements --name=<your_project_name>

You can follow the quick tutorial in the official Angular documentation to get started.

4. Aliases for Import Statements

This very useful feature is supported out of the box in Angular. I’m sure you’ve encountered instances where imports in your applications are just messy and difficult to read. You have something like:

    import { ThatComponent } from '../../../components/this-component/child-component'
    import { ThisService } from '../../../../services/this-service'

I’m sure it would be more helpful to have aliases for the components and services paths – this would make these imports relatively easy to read and import.

When working with React, I’ve researched how to achieve this, but most solutions involve ejecting your application, which doesn’t really sound pleasing. Well, to achieve this in your Angular application, all you need to do is to update the tsconfig.json file:

    {
      "compileOnSave": false,
      "compilerOptions": {
        "baseUrl": "src",
        "paths": {
          "@components": "app/components",
          "@services": "app/services",
        },
        "..."
      }
    }

What happened here is that the default value of the baseUrl property ./ was updated to point to the src directory. Then we added a new property called paths, which is an object containing key values pairs representing aliases defined for paths in our application. Aliases were defined for the components folder and the services folder. Now if we want to attempt the imports in the previous example, we’ll do this:

    import { ThatComponent } from '@components/this-component/child-component';
    import { ThisService } from '@services/this-service';

This is way cleaner and easier to read than the previous example. If you’ve not booted up your editor to do this for your application already, then you should get to it.

5. Safe Navigation Operator for String Interpolation

When working with objects in Angular templates, you encounter situations where variables are declared without default values – the variable is just presented as a type definition. When trying to access a property on the variable that isn’t readily available, Angular will throw an error saying the variable is undefined.

For example, your template looks like this, you’re reading the name property of a student object:

 

{{ student.name }}

And this was how the variable was declared in the component file:

    interface Student {
      name: String;
      age: Number:
    }
    
    @Component({
      selector: 'app-component',
    })
    export class AppComponent{
      student: Student;
    }

Angular will throw an error here.

Using the safe navigation operator, we can safeguard the name property against any null and undefined values. The safe navigation operator in Angular is this syntax ?., and we can update the template to use this:

 

{{ student?.name }}

When you run this, Angular doesn’t throw any errors and your console is clear. Another useful technique of avoiding this error is using the and (&&) operator to check if the value exists before reading the property path. We can update the example to use this syntax:

 

{{ student && student.name }}

If the value doesn’t exist, Angular will avoid evaluating the expression and nothing is rendered between the tags.

6. Handle Errors Properly with an Error Handler

Angular comes packed with an exception handling service that can be used to manage errors application-wide. When the service detects errors, it catches the error and logs it to the console. This service can be extended to add additional features unique to our application like logging the error using an error monitoring platform or sending the errors to your server for analytics.

The Error Handler is pretty easy to extend: We need to create a class that extends the properties of the ErrorHandler and overrides the built in handleError method used for displaying errors.

Create a file called error-handler.class.ts:

    import {ErrorHandler} from '@angular/core';
    // A fake error monitoring library
    import ErrorClient from '@error-reporters/core';
    
    // Initialize the report library
    const reporter = new ErrorClient();
    
    export class AppErrorHandler extends ErrorHandler {
        constructor(private errorService: ErrorService){
            super(false);
        }
    
        public handleError(error: any): void {
            reporter.sendReport(error)
            super.handleError(error);
        }
    }

In the snippet above, we made use of a fictional error reporting and monitoring library called @error-reporters. After extending the ErrorHandler service, we will report errors emanating from the application in the handleError method before handling the error with the ErrorHandler’s handleError method.

After that, we should register our custom AppErrorHandler in app.module.ts:

    @NgModule({
        declarations: [ AppComponent ],
        imports: [ BrowserModule ],
        bootstrap: [ AppComponent ],
        providers: [
            {provide: ErrorHandler, useClass: AppErrorHandler}
        ]
    })

You can read more on the default error handler by Angular here.

7. Lazy Load Non-Vital Components

When working on fairly large applications or starting up one, it will be helpful to ensure that components not needed for the initial render of your application are lazy loaded. Lazy loaded in the sense that they’re loaded on demand. For example, when a user navigates away from the initial view of the application, a network request is made to load the destination route. Lazy loading can effectively reduce the bundle size of your application, thus reducing the load time of the application on the browser.

Lazy loading components starts with creating a feature module in your application, the feature module will house the components, services, providers, etc. attached it. The feature module is then loaded in the root routing module of the application. Look at the example below:

    import { NgModule } from '@angular/core';
    import { CommonModule } from '@angular/common';
    import { FeatureRoutingModule } from './feature-routing.module';
    import { FeatureComponent } from './feature/feature.component';
    
    @NgModule({
      imports: [
        CommonModule,
        FeatureRoutingModule
      ],
      declarations: [FeatureComponent]
    })
    export class FeatureModule { }

This feature module FeatureModule contains a single component FeatureComponent and a routing module FeatureRoutingModule attached to it.

To lazy load this component, we’ll register the feature module’s routing module in the application’s root module:

    import { NgModule } from '@angular/core';
    import { FormsModule } from '@angular/forms';
    import { BrowserModule } from '@angular/platform-browser';
    import { RouterModule } from '@angular/router';
    
    import { AppComponent } from './app.component';
    
    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule,
        FormsModule,
        RouterModule.forRoot([
          {
            path: 'feature',
            loadChildren: './feature/feature.module#FeatureModule'
          }
        ])
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }

With this simple step, a separate bundle will be built apart from the main app bundle. This bundle will be loaded when the user navigates to the /feature route. The experience might be a bit unpleasant because the user will need to wait for the route’s bundle to be loaded, and this might take a while depending on the size of the bundle.

To fix this issue, we’ll prefetch the other bundles in the background once the initial page has been loaded fully. We can do this using a built-in flag provided by Angular called the preloadStrategy. This tells Angular which strategy to use when loading lazied bundles.

Let’s update the current implementation to use the PreloadAllModules strategy:

    import { NgModule } from '@angular/core';
    ...
    import { RouterModule, PreloadAllModules } from '@angular/router';
    
    import { AppComponent } from './app.component';
    
    @NgModule({
      declarations: [
       ...
      ],
      imports: [
        ...
        RouterModule.forRoot([
          {
            path: 'feature',
            loadChildren: './feature/feature.module#FeatureModule'
          }
        ], {preloadStrategy: PreloadAllModules})
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }

With this update, Angular will handle prefetching of feature bundles in the background for easy navigation.

Conclusion

Angular is a framework which means it has its way of doing things and producing results. It comes with so many features both popular and unknown, the easiest way to discover tricks to achieve difficult tasks using Angular is to use Angular a lot more and research more in the process. The tips and tricks listed above don’t fully cover the extent of what can be done using Angular’s extensive features.

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow us on Facebook | Twitter

Further reading

Angular 8 (formerly Angular 2) - The Complete Guide

Angular & NodeJS - The MEAN Stack Guide

The Web Developer Bootcamp

Angular 8 is coming

MEAN Stack Angular 8 CRUD Web Application

Angular 8 + Spring Boot 2.2: Build a CRUD App Today!

What are the best alternatives for angular js?

<img src="https://moriohcdn.b-cdn.net/193902114c.png">There are numerous frameworks and libraries used across the globe. If not angular, there are platforms like React, Vue, Aurelia and so on for app development.

There are numerous frameworks and libraries used across the globe. If not angular, there are platforms like React, Vue, Aurelia and so on for app development.

Angular 8 Node & Express JS File Upload

Angular 8 Node & Express JS File Upload

In this Angular 8 and Node.js tutorial, we are going to look at how to upload files on the Node server. To create Angular image upload component, we will be using Angular 8 front-end framework along with ng2-file-upload NPM package; It’s an easy to use Angular directives for uploading the files.

In this Angular 8 and Node.js tutorial, we are going to look at how to upload files on the Node server. To create Angular image upload component, we will be using Angular 8 front-end framework along with ng2-file-upload NPM package; It’s an easy to use Angular directives for uploading the files.

We are also going to take the help of Node.js to create the backend server for Image or File uploading demo. Initially, we’ll set up an Angular 8 web app from scratch using Angular CLI. You must have Node.js and Angular CLI installed in your system.

We’ll create the local server using Node.js and multer middleware. Multer is a node.js middleware for handling multipart/form-data, which is primarily used for uploading files. Once we are done setting up front-end and backend for our File uploading demo then, we’ll understand step by step how to configure file uploading in Angular 8 app using Node server.

Prerequisite

In order to show you Angular 8 File upload demo, you must have Node.js and Angular CLI installed in your system. If not then check out this tutorial: Set up Node JS

Run following command to install Angular CLI:

npm install @angular/cli -g

Install Angular 8 App

Run command to install Angular 8 project:

ng new angular-node-file-upload

# ? Would you like to add Angular routing? No
# ? Which stylesheet format would you like to use? CSS
cd angular-node-file-upload

Show Alert Messages When File Uploaded

We are going to install and configure ngx-toastr an NPM package which helps in showing the alert message when the file is uploaded on the node server.

npm install ngx-toastr --save

The ngx-toastr NPM module requires @angular/animations dependency:

npm install @angular/animations --save

Then, add the ngx-toastr CSS in angular.json file:

"styles": [
    "src/styles.css",
    "node_modules/ngx-toastr/toastr.css"
]

Import BrowserAnimationsModule and ToastrModule in app.module.ts file:

import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ToastrModule } from 'ngx-toastr';
 
@NgModule({
  imports: [
    CommonModule,
    BrowserAnimationsModule, // required animations module
    ToastrModule.forRoot() // ToastrModule added
  ]
})

export class AppModule { }

Install & Configure ng-file-upload Directive

In this step, we’ll Install and configure ng-file-upload library in Angular 8 app. Run command to install ng-file-upload library.

npm install ng2-file-upload

Once the ng2-file-upload directive is installed, then import the FileSelectDirective and FormsModule in app.module.ts. We need FormsModule service so that we can create the file uploading component in Angular.

import { FileSelectDirective } from 'ng2-file-upload';
import { FormsModule } from '@angular/forms';

@NgModule({
  declarations: [
    FileSelectDirective
  ],
  imports: [
    FormsModule
  ]
})

export class AppModule { }

Setting Up Node Backend for File Upload Demo

To upload the file on the server, we need to set up a separate backend. In this tutorial, we will be using Node & Express js to create server locally along with multer, express js, body-parser, and dotenv libraries.

Run command to create backend folder in Angular app’s root directory:

mkdir backend && cd backend

In the next step, create a specific package.json file.

npm init

Run command to install required dependencies:

npm install express cors body-parser multer dotenv --save

In order to get rid from starting the server again and again, install nodemon NPM package. Use –-save-dev along with the npm command to register in the devDependencies array. It will make it available for development purpose only.

npm install nodemon --save-dev

Have a look at final pacakge.json file for file upload demo backend:

{
  "name": "angular-node-file-upload",
  "version": "1.0.0",
  "description": "Angualr 8 file upload demo app",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node server.js"
  },
  "author": "Digamber Rawat",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.19.0",
    "cors": "^2.8.5",
    "dotenv": "^8.0.0",
    "express": "^4.17.1",
    "multer": "^1.4.1"
  },
  "devDependencies": {
    "nodemon": "^1.19.1"
  }
}

Create a file by the name of server.js inside backend folder:

Configure Server.js

To configure our backend we need to create a server.js file. In this file we’ll keep our backend server’s settings.

touch server.js

Now, paste the following code in backend > server.js file:

const express = require('express'),
  path = require('path'),
  cors = require('cors'),
  multer = require('multer'),
  bodyParser = require('body-parser');

// File upload settings  
const PATH = './uploads';

let storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, PATH);
  },
  filename: (req, file, cb) => {
    cb(null, file.fieldname + '-' + Date.now())
  }
});

let upload = multer({
  storage: storage
});

// Express settings
const app = express();
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: false
}));

app.get('/api', function (req, res) {
  res.end('File catcher');
});

// POST File
app.post('/api/upload', upload.single('image'), function (req, res) {
  if (!req.file) {
    console.log("No file is available!");
    return res.send({
      success: false
    });

  } else {
    console.log('File is available!');
    return res.send({
      success: true
    })
  }
});

// Create PORT
const PORT = process.env.PORT || 8080;
const server = app.listen(PORT, () => {
  console.log('Connected to port ' + PORT)
})

// Find 404 and hand over to error handler
app.use((req, res, next) => {
  next(createError(404));
});

// error handler
app.use(function (err, req, res, next) {
  console.error(err.message);
  if (!err.statusCode) err.statusCode = 500;
  res.status(err.statusCode).send(err.message);
});

Now, while staying in the backend folder run the below command to start the backend server:

nodemon server.js

If everything goes fine then you’ll get the following output:

[nodemon] 1.19.1
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `node server.js`
Connected to port 8080

Create Angular 8 File Upload Component

In this last step, we are going to create a file upload component in Angular 8 app using Express js API.

Get into the app.component.ts file and include the following code:

import { Component, OnInit } from '@angular/core';
import { FileUploader } from 'ng2-file-upload/ng2-file-upload';
import { ToastrService } from 'ngx-toastr';

const URL = 'http://localhost:8080/api/upload';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent implements OnInit {
  public uploader: FileUploader = new FileUploader({
    url: URL,
    itemAlias: 'image'
  });

  constructor(private toastr: ToastrService) { }

  ngOnInit() {
    this.uploader.onAfterAddingFile = (file) => {
      file.withCredentials = false;
    };
    this.uploader.onCompleteItem = (item: any, status: any) => {
      console.log('Uploaded File Details:', item);
      this.toastr.success('File successfully uploaded!');
    };
  }

}

Go to app.component.html file and add the given below code:

<div class="wrapper">
  <h2>Angular Image Upload Demo</h2>

  <div class="file-upload">
    <input type="file" name="image" ng2FileSelect [uploader]="uploader" accept="image/x-png,image/gif,image/jpeg" />
    <button type="button" (click)="uploader.uploadAll()" [disabled]="!uploader.getNotUploadedItems().length">
      Upload
    </button>
  </div>

</div>

Now, It’s time to start the Angular 8 app to check out the File upload demo in the browser. Run the following command:

ng serve --open

Make sure your NODE server must be running to manage the backend.

When you upload the image from front-end you’ll see your image files are saving inside the backend > uploads folder.

Conclusion

In this Angular 8 tutorial, we barely scratched the surface related to file uploading in a Node application. There are various other methods available on the internet through which you can achieve file uploading task quickly. However, this tutorial is suitable for beginners developers. I hope this tutorial will surely help and you if you liked this tutorial, please consider sharing it with others.

Angular JS Development Company

If you’re finding AngularJS Development Company for consultation or Development, your search ends here at Data EximIT 

🔗 Click here to know more: AngularJS Development