In this blog, I am going to demonstrate the process of staring a new Angular project and creating an application.
Preparing a TypeScript Angular Development Environment
You need to have a selected code editor. Here, in my case, I have selected VS 2015. Along with that, I have installed a recent browser, and a recent version of Node.js.
I have started by creating a project in Visual Studio by selecting File >> New >> Project.
Create a project with a name as you wish. Here, I have selected the name as ProductCart which suits to my project description.
Select Empty project and MVC as a core reference. As most of us come from .NET MVC background, this makes us more comfortable to see similar things.
A Two-folder structure is required for an Angular application. The first one contains all the project files and the second folder has all the code.
Now, the recently created project needs some of the folders to be deleted, as highlighted below.
The structure of our project looks like below
HTML 5 is required to load the JavaScript files and start the application. Create a default index file.
Index.Html
- <!DOCTYPEhtml>
- <html>
-
- <head>
- <title>Test 1</title>
- <metacharset="utf-8" />
- </head>
-
- <body>
- <app>Welcome to angular</app>
- </body>
-
- </html>
An Angular project needs a lot of software packages. Let us install or download them using the Node Package Manager (NPM).To add these packages, I have added the package.json file.
- {
- "dependencies": {
- "@angular/common": "2.2.0",
- "@angular/compiler": "2.2.0",
- "@angular/core": "2.2.0",
- "@angular/platform-browser": "2.2.0",
- "@angular/platform-browser-dynamic": "2.2.0",
- "@angular/upgrade": "2.2.0",
- "@angular/forms": "2.2.0",
- "@angular/http": "2.2.0",
- "reflect-metadata": "0.1.8",
- "rxjs": "5.0.0-beta.12",
- "zone.js": "0.6.26",
- "core-js": "2.4.1",
- "classlist.js": "1.1.20150312",
- "systemjs": "0.19.40",
- "bootstrap": "4.0.0-alpha.4"
- },
- "decDependencies": {
- "lite-server": "2.2.2",
- "typescript": "2.0.2",
- "typings": "2.1.1",
- "concurrently": "2.2.0"
- },
- "scripts": {
- "start": "concurrently \"npm run tswatch\" \"npm run lite \" ",
- "tsc": "tsc",
- "tswatch": "tsc -w",
- "lite": "lite-server",
- "typings": "typings"
- }
- }
Now, it's time to install the packages in the project. Open the npm command prompt and go to the project directory and run the npm install command.
Check the solution. There must be a new folder inside the project node_modules.
Type definition is the definition used by TypeScript to work on JavaScript libraries. The following website manages the types that I have added to the package.json.
http://definitelytyped.org
Run the following command in the project folder to download and install the TypeScript files. Hence, these are required by the project.
- npm run typings - - install dt~core-js - -save - - global
- npm run typings - - install dt~node - - save - - global
When these commands run, the project will use the scripts section of the package.json file and use the typings package to download the packages.
A folder named Typings will be added to the project and a new option of TypeScript build will appear in the project properties.
It will add a file called typing.json.
Typing.json
- {
- "globalDependencies": {
- "core-js": "registry:dt/core-js#0.9.0+20170324193834",
- "node": "registry:dt/node#7.0.0+20170322231424"
- }
- }
To use the TypeScript complier, we need to create tsconfig.json file as I have created below.
tsconfig.json
- {
- "compilerOptions": {
- "target": "es6",
- "module": "commonjs",
- "sourceMap": true,
- "moduleResolution": "node",
- "emitDecoratorMetadata": true,
- "experimentalDecorators": true,
- "noStrictGenericChecks": true
- },
- "exclude": ["node_modules"]
- }
Add a file comilertest.ts to the project and test your compiler.
I have created a model file Product.model.ts.
Product.model.ts
- exportclass Product {
- constructor(public id ? : number, public name ? : string, public category ? : string, public price ? : number) {}
- }
Now, our model is ready to create a data source for the application. I have created a simple data souce named datasource.model.ts
Datasource.model.ts
- import {
- Product
- } from "./product";
- exportclass SimpleDataSource {
- private data: Product[];
- constructor() {
- this.data = new Array < Product > (new Product(1, "Kayak", "Watersports", 275), new Product(2, "Lifejacket", "Watersports", 48.95), new Product(3, "Soccer Ball", "Soccer", 19.50), new Product(4, "Corner Flag", "Soccer", 34.95), new Product(5, "Thinking Cap", "Chess", 16));
- }
- getData(): Product[] {
- returnthis.data;
- }
- }
Finally, create a repository with Save, Delete, and getproducts methods. I have created it as repository.model.ts
Repository.model.ts
- import {
- Product
- } from "./product";
- import {
- SimpleDataSource
- } from "./datasource";
- exportclass Model {
- private datasource: SimpleDataSource;
- private products: Product[];
- private locator = (p: Product, id: number) => p.id == id;
- constructor() {
- this.datasource = new SimpleDataSource();
- this.products = new Array < Product > ();
- this.datasource.getData().forEach(p => this.products.push(p));
- }
- getProdcts(): Product[] {
- returnthis.products;
- }
- getProducts(id: number): Product {
- returnthis.products.find(p => this.locator(p, id));
- }
- saveProduct(product: Product) {
- if (product.id == null || product.id == 0) {
- product.id = 1;
- this.products.push(product);
- } else {
- let index = this.products.findIndex(p => this.locator(p, p.id));
- this.products.splice(index, 1, product);
- }
- }
- deleteProduct(id: number) {
- let index = this.products.findIndex(p => this.locator(p, id));
- this.products.slice(index, 1);
- }
- generateID(): number {
- let candidate = 100;
- while (this.getProducts(candidate) != null) {
- candidate++;
- }
- return candidate;
- }
- }
Now, let's start creating the template and root component for our productcart.
For now, I will keep my template simple and later at the end, I will modify it to show you Angular in action.
Template.html
- <div class=”bg-info p-a-1”> This is my first angular app. </div>
All the code is written in component, a TypeScript class. The @Component decorator is applied to this class.
Component.ts
- import {
- Component
- } from "@angular/core";
- import {
- Model
- } from "./repository.model";
- import {
- Product
- } from "./Product.model";
- @Component({
- selector: "app",
- templateUrl: "app/template.html"
- })
- exportclass ProductComponent {
- model: Model = new Model();
- getProducts(): Product[] {
- returnthis.model.getProdcts();
- }
- }
App modules is a root module for describing the application. I have added one, i.e., app.module.ts.
App.module.ts
- import { NgModule } from"@angular/core";
- import { BrowserModule } from"@angular/platform-browser";
- import { ProductComponent } from"./component";
- @NgModule({
- declarations: [ProductComponent,],
- imports: [BrowserModule],
- bootstrap: [ProductComponent]
- })
- exportclass AppModule { }
We need to bootstrap the application so as to enable the communication in Angular framework and the application code. For that, I have defined a class below, named as main.ts.
Main.ts
- import { platformBrowserDynamic } from"@angular/platform-browser-dynamic";
- import { AppModule } from"./app.module";
- platformBrowserDynamic().bootstrapModule(AppModule);
Now, we have to create a module loader to load the dependent files.
Systemjs.config.js
- (function(global) {
- var paths = {
- "rxjs/*": "node_modules/rxjs/bundles/Rx.min.js",
- "@angular/*": "node_modules/@angular/*"
- }
- var packages = {
- "app": {}
- };
- var angularModules = ["forms", "common", "compiler", "core", "platform-browser", "platform-browser-dynamic"]
- angularModules.forEach(function(pkg) {
- packages["@angular/" + pkg] = {
- main: "/bundles/" + pkg + ".umd.min.js"
- };
- });
- System.config({
- paths: paths,
- packages: packages
- });
- })(this);
Finally, here comes the end to include the JS files not loaded in the Module loader.
Index.html
- <!DOCTYPEhtml>
- <html>
-
- <head>
- <title>Angular</title>
- <metacharset="utf-8" />
- <scriptsrc="node_modules/classlist.js/classList.min.js"> </script> <scriptsrc="node_modules/core-js/client/shim.min.js">
- </script>
- <scriptsrc="node_modules/zone.js/dist/zone.min.js"> </script> <scriptsrc="node_modules/reflect-metadata/Reflect.js">
- </script>
- <scriptsrc="node_modules/systemjs/dist/system.src.js"> </script> <scriptsrc="systemjs.config.js">
- </script>
- <script>
- System.import("app/main").catch(function(err) {
- console.error(err);
- });
- </script>
- <linkhref="node_modules/bootstrap/dist/css/bootstrap.min.css"rel="stylesheet"/> </head> <bodyclass="m-a-1">
- <app>
- </app>
- </body>
-
- </html>
Now, let us build and run the application. Shown below is the result.
I have added another step for you guys to iterate and display the product cart in template.html.
- <tableclass="table table-sm table-bordered m-t-1">
- <tr>
- <th>Name</th>
- <th>Category</th>
- <th>Price</th>
- </tr>
- <tr*ngFor="let item of getProducts()">
- <td>{{item.name}}</td>
- <td>{{item.category}}</td>
- <td>{{item.price}}</td>
- </tr>
- </table>
Template.html
- <divclass="bg-info p-a-1"> There are {{getProductNumber()}} products. <br />
- <tableclass="table table-sm table-bordered m-t-1">
- <tr>
- <th>Name</th>
- <th>Category</th>
- <th>Price</th>
- </tr>
- <tr*ngFor="let item of getProducts()">
- <td>{{item.name}}</td>
- <td>{{item.category}}</td>
- <td>{{item.price}}</td>
- </tr>
- </table>
- </div>