Click here to Skip to main content
13,899,972 members
Click here to Skip to main content
Add your own
alternative version

Stats

10.6K views
358 downloads
9 bookmarked
Posted 22 Sep 2017
Licenced CPOL

Learn Angular Tutorial - Part 5

, 22 Sep 2017
Rate this:
Please Sign up or sign in to vote.
This part 5 of Learn Angular Tutorial. In this we will see how to implement Lazy loading and how we can use Jquery with Angular.

Contents

Lab 11:- Lazy loading using dynamic routes

Lab 12: - Using jQuery with Angular

Links to rest of the articles

In this article we will see how to implement lazy routing and how to use Jquery with Angular.

Lab 11:- Lazy loading using dynamic routes

Theory

Big projects will have lot of components and modules, in other words we will end up with lot of JS files on the browser client side. Loading these JS files in ONE GO at the client browser side would really hit performance.

If you load the current application at this stage and see the developer tools you will see on the network tab all JS files are getting loaded at the start.

When the first time the user comes to the site we would like to just load the welcome component and master component JS only.

When the user clicks on supplier and customer respective JS files should be loaded at that moment.

 

 

Let’s investigate who is the culprit ?.

If you see the current architecture of our project we have one module(MainModule.ts) and all components current belong to this only ONE Module. So when this module loads it loads all components inside it.

In simple words we need to BREAK MODULES in to separate physical module files.

 

Step 1 :- Creating three different physical modules

So as discussed in the previous part of the theory we need to first divide our project in to three different physical module files: - MainModule , SupplierModule and CustomerModule.

So in the module folder lets create three different physical module files. We already have MainModule.ts we need to create two more.

MainModule.ts :- This module will load “MasterPageComponent.ts” and “WelcomeComponent.ts”.

SupplierModule.ts :- This module will load “SupplierComponent.ts”.

CustomerModule.ts :- This will load CustomerComponent and GridComponent. Remember grid is used only in Customer UI so this should load only when Customer functionality is loaded.

 

Step 2 :- Removing Supplier and Customercomponent from MainModule

The first thing is we need to remove all references of CustomerComponent,SupplierComponent and GridComponent from the MainModule. Below is the striked out source code which needs to be removed from the MainModule. In the main module, we only have reference to WelcomeComponent and MastePageComponent.

 Two modules are decoupled from each other when import does not exist between those modules. Even if you do not use the component and there is an import decoupling is not complete and the JS will be loaded.

Lot of Code has been removed for clarity. Please download source code
for full code.
import { CustomerComponent }   from '../Component/CustomerComponent';
import { SupplierComponent }   from '../Component/SupplierComponent';
import { WelcomeComponent }   from '../Component/WelcomeComponent';
import { GridComponent }   from '../Component/GridComponent';
import { MasterPageComponent }   from '../Component/MasterPageComponent';

@NgModule({
    imports: [RouterModule.forRoot(ApplicationRoutes), 
        InMemoryWebApiModule.forRoot(CustomerApiService),
             BrowserModule,ReactiveFormsModule,
             FormsModule,HttpModule],
    declarations: [CustomerComponent,
                MasterPageComponent,
                SupplierComponent,
                WelcomeComponent, 
                GridComponent],
    bootstrap: [MasterPageComponent]
})
export class MainModuleLibrary { }

Step 3 :- Creating different Route files

As said previously “A SIMPLE IMPORT REFERENCE” will make two modules coupled. If the modules are coupled those JS files will be loaded.

If you remember “MainModule.ts” loads the Routes from “Routing.ts” and Routing.ts has import references to SupplierComponent and CustomerComponent.

So loading routing will load the other components as well and we will not be able to achieve lazy loading.

So let us remove all references of Customer and Supplier component from MainModule.ts , see the striked out code down below.

 

import {Component} from '@angular/core';
import {CustomerComponent} from '../Component/CustomerComponent';
import {SupplierComponent} from "../Component/SupplierComponent";
import {WelcomeComponent} from "../Component/WelcomeComponent";
export const ApplicationRoutes = [
    { path: 'Customer', component: CustomerComponent },
    { path: 'Supplier', component: SupplierComponent },
     { path: '', component:WelcomeComponent  },
    { path: 'UI/Index.html', component:WelcomeComponent  }
];

But still we need to still define routes for “Customer” and “Supplier” and the same time not use “import” statement as that makes the module coupled. If you look at the current syntax of defining route we need to have that component in the import or else we cannot define the route.

{ path: 'CustomerComponent', component:CustomerComponent  },

For that Angular has given a nice property called as “loadChildren”. In “loadChildren” we need to give the module in a single quote like a string. Which means that this thing will be evaluated during run time and now compile time.

{ 
path: 'Customer',
loadChildren:'../Module/CustomerModuleLibrary#CustomerModuleLibrary' 
}

The structure of “loadChildren” should follow this pattern: -

The full code of the route will look something as shown below.

import {Component} from '@angular/core';
import {WelcomeComponent} from "../Component/WelcomeComponent";
export const ApplicationRoutes = [
    { path: 'Customer', 
loadChildren:'../Module/CustomerModuleLibrary#CustomerModuleLibrary' },
    { path: 'Supplier', 
loadChildren: '../Module/SupplierModuleLibrary#SupplierModuleLibrary' },
     { path: '', component:WelcomeComponent  },
    { path: 'UI/Index.html', component:WelcomeComponent  },
    { path: 'UI', component:WelcomeComponent  }
];

We also need to create two more route files one for “Customer” and one for “Supplier” as shown below.

import {Component} from '@angular/core';
import {CustomerComponent} from "../Component/CustomerComponent";
export const CustomerRoutes = [
    { path: 'Add', component:CustomerComponent  }
];
import {Component} from '@angular/core';
import {SupplierComponent} from "../Component/SupplierComponent";
export const SupplierRoutes = [
    { path: 'Add', component:SupplierComponent  }
];

“SupplierRoutes” and “CustomerRoutes” are child routes while the “ApplicationRoutes” is the parent route.

Step 4 :- Calling Child routes in Supplier and Customer modules

In supplier module and customer modules we need to load their respective routes defined in “Step 3”. To load child routes we need to use “RouterModule.forChild”.

import { NgModule }      from '@angular/core';
import { CommonModule } from '@angular/common';
import {FormsModule , ReactiveFormsModule} from "@angular/forms"
import { SupplierComponent }   from '../Component/SupplierComponent';
import { RouterModule }   from '@angular/router';
import { SupplierRoutes }   from '../Routing/SupplierRouting';   
import {CustomerApiService} from "../Api/CustomerApi"
@NgModule({
    imports: [RouterModule.forChild(SupplierRoutes),
             CommonModule,ReactiveFormsModule,
             FormsModule],
    declarations: [SupplierComponent],
    bootstrap: [SupplierComponent]
})
export class SupplierModuleLibrary { }

Same way we need to for Customer Module.

import { NgModule }      from '@angular/core';
import { CommonModule } from '@angular/common';
import {FormsModule , ReactiveFormsModule} from "@angular/forms"
import { CustomerComponent }   from '../Component/CustomerComponent';
import { GridComponent }   from '../Component/GridComponent';
import { RouterModule }   from '@angular/router';
import { CustomerRoutes }   from '../Routing/CustomerRouting';   
import { InMemoryWebApiModule } from 'angular2-in-memory-web-api';
import {CustomerApiService} from "../Api/CustomerApi"
import { HttpModule } from '@angular/http';

@NgModule({
    imports: [RouterModule.forChild(CustomerRoutes), 
        InMemoryWebApiModule.forRoot(CustomerApiService),
             CommonModule,ReactiveFormsModule,
             FormsModule,HttpModule],
    declarations: [CustomerComponent, 
                GridComponent],
    bootstrap: [CustomerComponent]
})
export class CustomerModuleLibrary { }

Step 5 :- Configuring routerlinks

In step 3 and 4 we have defined parent routes and child routes. Parent routes are defined in “Routing.ts” while child routes are defined in “CustomerRouting.ts” and “SupplierRouting.ts”. So now the router link has to be changed to “Supplier/Add” and “Customer/Add” as shown in the below code.

 

<a [routerLink]="['Supplier/Add']">Supplier</a> <br />
<a [routerLink]="['Customer/Add']">Customer</a><br>

So now the full code look of master page looks as shown below.

<table border="0" width="100%">
<tr>
<td width="20%"><img src="http://www.questpond.com/img/logo.jpg" alt="Alternate Text" />
</td>
<td width="80%">Questpond.com Private limited</td>
</tr>
<tr>
<td valign=top>Left Menu<br />
<a [routerLink]="['Supplier/Add']">Supplier</a> <br />
<a [routerLink]="['Customer/Add']">Customer</a><br>
<a [routerLink]="['']">Home</a>
</td>
<td>
<div id="dynamicscreen">
<router-outlet></router-outlet>
</div>
</td>
</tr>
<tr>
<td></td>
<td>Copy right @Questpond</td>
</tr>
</table>

Step 6 :- Replacing browser module with common module

“BrowserModule” and “CommonModule” are modules of angular. “BrowserModule” has code which starts up services and launches the application while “CommonModule” has directives like “NgIf” and “NgFor”.
“BrowserModule” re-exports “CommonModule”. Or if I put in simple words “BrowserModule” uses “CommonModule”. So if you are loading “BrowserModule” you are loading “CommonModule” also.

So now if you are loading “BrowserModule” in all three modules then you will end uploading “CommonModule” 3 times. When you are doing Lazy Loading you really do not want to load things 3 times , it should be loaded only once.

So if you have “BrowserModule” in all three modules then you would end up getting such kind of error as shown in below figure.

This error says “BrowserModule” has already been loaded in the “MainModule” please use “CommonModule” in “CustomerModule” and “SupplierModule”.

 

So in main module load the browser module and in rest of modules load “CommonModule”.

import { BrowserModule } from '@angular/platform-browser';
// Other imports have been removed for clarity
@NgModule({
    imports: [RouterModule.forRoot(ApplicationRoutes),
        InMemoryWebApiModule.forRoot(CustomerApiService),
             BrowserModule,ReactiveFormsModule,
             FormsModule,HttpModule],
    declarations: [
                MasterPageComponent,
                WelcomeComponent],
    bootstrap: [MasterPageComponent]
})
export class MainModuleLibrary { }

But in customer and supplier module just load common module.

import { CommonModule } from '@angular/common';
// other imports has been removed for clarity

@NgModule({
    imports: [RouterModule.forChild(SupplierRoutes),
             CommonModule,ReactiveFormsModule,
             FormsModule],
    declarations: [SupplierComponent],
    bootstrap: [SupplierComponent]
})
export class SupplierModuleLibrary { }
import { CommonModule } from '@angular/common';
// Other import has  been removed for claroty
@NgModule({
    imports: [RouterModule.forChild(CustomerRoutes),
        InMemoryWebApiModule.forRoot(CustomerApiService),
             CommonModule,ReactiveFormsModule,
             FormsModule,HttpModule],
    declarations: [CustomerComponent,
                GridComponent],
    bootstrap: [CustomerComponent]
})
export class CustomerModuleLibrary { }

Step 7 :- Check if Lazy loading is working

Now run your application , go to network tab and check if lazy loading is working. You can see when the application run at the start only “WelcomeComponent” and “MasterPageComponent” is loaded. Once you click on supplier and customer the respective components will loaded at that time.

Please put a proper filter so that you do not see all JS files in your network.

Lab 12: - Using jQuery with Angular

Introduction

jQuery is a very old and trusted JavaScript framework. It has lot of UI components which are stable and trusted. As a practice, you should not use jQuery with Angular because both of them can overlap with DOM manipulation causing confusion.

jQuery manipulates HTML DOM directly using “$” syntaxes while Angular creates a sugar-coated DOM over HTML DOM and does the manipulation via this sugar-coated DOM.

So jQuery can manipulate HTML DOM without Angular not having knowledge about this manipulation creating more confusion.

But then there are instances when we would like to use jQuery UI components like jQuery grids, jQuery calendar and so on which probably are not available in Angular.

  If Angular is your prime framework then first see that you get your solution inside Angular if not then use jQuery or any other framework.

 

In this lab we will use jQuery to fade away and fade in our grid component. So let’s create a button with name Hide grid. When the end user clicks on hide grid the grid should gradually become visible and invisible.

Step 1 :- Install Jquery

So the first step is to get jQuery. Let’s fire up the node command and also let’s get jQuery as well as lets save the entry in to “package.json” file.

npm install jquery –save

Step 2 :- Install Jquery typings

JavaScript is divided in to two generations, one generation before typescript i.e. pure JavaScript and other generation after typescript. JavaScript is a dynamic and an untyped language while typescript is strongly typed. We can call methods which does not exist, assign variables which are not created as so on.

On other side typescript is strongly typed. Everything is done during design time / compile time, typescript has to know the methods, parameters everything upfront.

Now frameworks like jQuery are made in pure JavaScript, so if they need to be used in typescript we need to expose their types, parameters and so on. That’s where we need to create typing files. Typing’s are typescript files which expose the shape and structure of JavaScript objects so that typescript can understand JavaScript types during design time.

You must be wondering so do we need to create the typing’s file manually ?. No you do not need to. jQuery already has typing’s on the contrary almost all popular JavaScript frameworks have their typing’s file.

So to get the jQuery typing’s we need to do npm install by pointing at “@types/jquery”. In fact you can load any types by using “@types” for example if you want to load lodash you can do “npm install” on “@types/lodash”.

npm install @types/jquery –save

Step 3 :- Providing ID’s in the UI

jQuery references HTML UI elements using selectors. In selectors, we need to provide name or ids by which we can get reference of that HTML element. So let’s wrap our “grid” component inside a DIV tag and lets assign some “id” value to it , like the one we have given in the below code “divgrid”.

Also we have created a button which calls the “Fade” methods from the component.

<input (click)="Fade()" type="button" value="Hide Grid"/>
<div id="divgrid">
<grid-ui 

      [grid-columns]="[{'colName':'CustomerCode'},{'colName':'CustomerName'},{'colName':'CustomerAmount'}]" 

    [grid-data]="Customers" 

    (grid-selected)="Select($event)"></grid-ui>
<div>

Step 4 :- Importing and using Jquery in Component

Now the first things is to import jQuery in to your component file. For that we need to use the below code. You can see the import statement is bit differently used. We are using “*” and “as” keyword. “*” means we want to refer full JQuery file and “$” is the alias by which we will be referring jQuery syntax in the code.

import * as $ from "jquery";

Once jQuery has been imported we can now use “$” to execute jQuery syntaxes. You can see we have created a method called as “Fade” in which we are referring the HTML DIV ID and calling the “fadeToggle” method to fade in and out.

import * as $ from "jquery";
export class CustomerComponent {
   // Code removed for clarity
   Fade(){
        $("#divgrid").fadeToggle(3000);
    }
	   }

Step 5:- Make entry in to Systemjs.config.js

Our JS files are loaded using SystemJS module loader. So we need to make an entry in to “Systemjs.config.js” file stating where the jQuery file is located.

'jquery': '../node_modules/jquery/dist/jquery.js'

If you see we have specified the folder path as “dist”. “dist” stands for distribution folder. The final compiled copy of jQuery is in this folder so we have specified the same.

Now run the program and see the output. If you click on the “Hide” button you should see the grid fading out and in.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author


You may also be interested in...

Comments and Discussions

 
GeneralMessage Closed Pin
3-Jun-18 22:12
memberMember 138371233-Jun-18 22:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web04 | 2.8.190306.1 | Last Updated 22 Sep 2017
Article Copyright 2017 by Shivprasad koirala
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid