This article explains the fundamentals of Angular by creating a simple Angular application with Visual Studio 2017 using the default template available with .NET Core.
In this article, the following concepts have been covered.
- Creating an Angular App with .NET Core using Visual Studio 2017
- Adding component files manually.
- Adding component files by using inbuilt template and customization.
- A faster way to add a file in Visual Studio.
- Routing
- Data Binding
- Display JSON data from a file.
- Use of *ngIf & *ngFor .
- Apply Paging using “ngx-pagination”.
- Installing npm package with Visual Studio 2017
- Installfing an npm package through Quick package install.
- Installing an npm package through “Open Command Line”.
- Getting an npm package by making changes in the “package.json” file.
- Getting Data from an API Service
Creating an Angular Project with .NET Core using Visual Studio 2017
Step 1
Open Visual Studio 2017.
Step 2
Go to File >> New >> Project… (Ctrl + Shift + N).
Step 3
Select “ASP.NET Core Web Application”.
Select “ASP.NET Core Web Application” template in the “New Project” window and provide other details, as shown in the following screenshot and click OK.
Step 4 - Select Angular Template
It will take a while to create a new Angular app. Following is the screenshot of the newly created Angular app with .NET Core.
Step 5 - Run the application
Run the application with Google Chrome as the default browser.
You may see the debugging window for a while as shown in the preceding screenshot because Visual Studio 2017 Support JavaScript/TypeScript debugging. You can explore more about JavaScript and Typescript debugging in the following article,
After a while, you will see the running window with the home page. Following is the screenshot of the same.
You can explore “Counter” and “Fetch data” pages as well.
Routing
You have seen that the default application has been created as a small working example along with essential features like routing, data binding, calling a .NET Core API service from Angular App and other things have been implemented already. If you would like to explore, then you can explore this application by yourself as well. However, if you are new to Angular, then it will take some time to explore it.
I just want to start with the simplest one for routing rather than mixing the concepts. So just add a simple page for a calculator which does not require any dummy data from JSON file or data from API Service.
Add a new component manually.
Add a new folder “calculate” and 3 files inside this folder
- component.html
- component.ts
- component.css
Following is the screenshot of the same.
Faster way to add files in Visual Studio
If you would like to make file adding process faster then you can use “Add New File” extension which can be downloaded from here. After that just Press Shift +F2 to add a new file. Following are few screenshots showing that how faster we can add a file (or file with a folder) in Visual Studio.
Content of “~\app\components\calculate\calculate.component.ts”
- import { Component } from '@angular/core';
-
- @Component({
- selector: 'calculate',
- templateUrl: './calculate.component.html',
- styleUrls: ['./calculate.component.css']
- })
- export class CalculateComponent {
- }
Content of “~\app\components\calculate\calculate.component.html”
- <h1>Calculator Using Angular & TypeScript</h1>
-
- <br />
- <div>
- <div class="row">
- <div class="col-sm-4">
- <label>First Number: </label>
- </div>
- <div>
- </div>
- <div class="col-sm-4">
- <input type="number" placeholder="Enter First Number">
- </div>
- </div>
- <br />
- <div class="row">
- <div class="col-sm-4">
- <label>Second Number: </label>
- </div>
- <div class="col-sm-4">
- <input type="number" placeholder="Enter Second Number">
- </div>
- </div>
- <br />
- <div class="row">
- <div class="col-sm-4">
- <label>Result: </label>
- </div>
- <div class="col-sm-4">
- </div>
- </div>
- <br />
-
- <div class="row">
- <div class="col-sm-3">
-
- </div>
- <div class="col-sm-2">
- <button type="button" class="btn btn-primary">Add (∑)</button>
- </div>
-
- <div class="col-sm-2">
- <button type="button" class="btn btn-primary">Sub (−)</button>
- </div>
-
- <div class="col-sm-2">
- <button type="button" class="btn btn-primary">Mult (∗)</button>
- </div>
-
- <div class="col-sm-3">
- </div>
- </div>
- </div>
Content of “~\app\components\calculate\calculate.component.css”.
- .btn-primary {
- color: #fff;
- background-color: #0495c9;
- border-color: #357ebd;
- }
-
- .btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active, .open > .dropdown-toggle.btn-primary {
- color: #fff;
- background-color: #1704c9;
- border-color: #285e8e;
- }
Go to the file “~\app\app.shared.module.ts” and make the following changes
- add the following line in the import section
import { CalculateComponent } from './components/calculate/calculate.component';
- inside declarations section add
CalculateComponent
- inside forRoot([]) add
{ path: 'calculate', component: CalculateComponent }
Following is the screenshot of the same.
Add following line in the file “…\app\components\navmenu\navmenu.component.html”.
- <li [routerLinkActive]="['link-active']">
- <a [routerLink]="['/calculate']">
- <span class='glyphicon glyphicon-th-list'></span> Calculate
- </a>
- </li>
Following is a screenshot of the same.
Run the application. Once application launched to go to the Calculate page.
Finally, the routing task has been done, and we can navigate and access newly added page. However, if I will try to do the calculation on the newly added page, then we would not be able to do that. Because till now I have not added any data binding logic means nothing has been done yet to pass data from Component to Template and vice versa.
Data Binding
Data binding is an essential feature of any application and Angular provides multiple ways of data binding. Data binding a broad discussion topic and cannot be covered in a small section. So right now, I am going give brief about it.
Let’s have a quick look at the Angular data binding.
There are 4 different ways of data binding in Angular
- Interpolation
- Property Binding
- Event Binding
- Two-way Binding
Interpolation
Interpolation is one of the most popular ways of data binding. If you are coming from AngularJS background or C#, then you must have used interpolation already. In the same way, we can use interpolation in Angular. Interpolation is used to pass data from component to template or evaluate the inline expressions.
Syntax
{{Expression to evaluate}}
Example
Result: {{result}}
Property Binding
Property binding is used to pass data from component to template. It can be used with property, style, CSS class, style and so forth.
Syntax
[target] = "expression"
Example
- <span [innerText]="greet"></span> : {{userName}}
- <input type="text" [value]="userName" readonly />
Event Binding
Syntax
(target) = "statement"
Example
<button type="button" (click)="add()"> Add </button>
Two-way Binding
Syntax
[(target)] = "expression"
Example
<input [(ngModel)]="firstNumber" type="number" placeholder="Enter First Number">
Adding calculation logic & data binding to calculate component
Code changes for calculate.component.ts
Go back to calculator page. Open file “calculate.component.ts” and write following line inside CalculateComponent class.
- public firstNumber: number;
- public secondNumber: number;
- public result: number;
-
- public add() {
- this.result = this.firstNumber + this.secondNumber;
- }
-
- public sub() {
- this.result = this.firstNumber - this.secondNumber;
- }
-
- public mult() {
- this.result = this.firstNumber * this.secondNumber;
- }
Complete code for calculate.component.ts
- import { Component } from '@angular/core';
-
- @Component({
- selector: 'calculate',
- templateUrl: './calculate.component.html',
- styleUrls: ['./calculate.component.css']
- })
- export class CalculateComponent {
-
- public firstNumber: number;
- public secondNumber: number;
- public result: number;
-
- public add() {
- this.result = this.firstNumber + this.secondNumber;
- }
-
- public sub() {
- this.result = this.firstNumber - this.secondNumber;
- }
-
- public mult() {
- this.result = this.firstNumber * this.secondNumber;
- }
- }
Code changes for calculate.component.html
Open the file “calculate.component.html” and change the code to implement Two-way binding for first and second number.
- <input [(ngModel)]="firstNumber" type="number" placeholder="Enter First Number">
- <input [(ngModel)]="secondNumber" type="number" placeholder="Enter Second Number">
and use string interpolation for displaying the result
<label>{{result}} </label>
Add Event binding code for add, subtract and multiply button.
- <button type="button" (click)="add()" class="btn btn-primary"> Add (∑)</button>
- <button type="button" (click)="sub()" class="btn btn-primary"> Sub (−)</button>
- <button type="button" (click)="mult()" class="btn btn-primary"> Mult (∗)</button>
Complete code for calculate.component.html
- <h1>Calculator Using Angular & TypeScript</h1>
-
- <br />
- <div>
- <div class="row">
- <div class="col-sm-4">
- <label>First Number: </label>
- </div>
- <div>
- </div>
- <div class="col-sm-4">
- <input [(ngModel)]="firstNumber" type="number" placeholder="Enter First Number">
- </div>
- </div>
- <br />
- <div class="row">
- <div class="col-sm-4">
- <label>Second Number: </label>
- </div>
- <div class="col-sm-4">
- <input [(ngModel)]="secondNumber" type="number" placeholder="Enter Second Number">
- </div>
- </div>
- <br />
- <div class="row">
- <div class="col-sm-4">
- <label>Result: </label>
- </div>
- <div class="col-sm-4">
- <label>{{result}} </label>
- </div>
- </div>
- <br />
-
- <div class="row">
- <div class="col-sm-3">
-
- </div>
- <div class="col-sm-2">
- <button type="button" (click)="add()" class="btn btn-primary">Add (∑)</button>
- </div>
-
- <div class="col-sm-2">
- <button type="button" (click)="sub()" class="btn btn-primary">Sub (−)</button>
- </div>
-
- <div class="col-sm-2">
- <button type="button" (click)="mult()" class="btn btn-primary">Mult (∗)</button>
- </div>
-
- <div class="col-sm-3">
- </div>
- </div>
- </div>
Run the application and calculate
Now rerun the application. Following is the screenshot of a running application, as you can see that now calculation logic is working fine. I have done summation; you can test it for subtraction and multiply as well.
Add a new component using the Angular Item templates option available in Visual Studio 2017.
Previously, you have seen that I have added calculate component, similarly add another component “customer”.
This time, I will not be adding a new component manually. I will add it using a template. Let’s have a look how we can add it using a template.
Right click on “component” folder >> Add >> New Item…
or you can use the keyboard shortcut “Ctrl + Shift + A”.
Check if “Angular Item Templates” is already installed or not.
If not, then please install it and re-open this window after installation.
Navigate to Installed >> Visual C# >> ASP.NET Core >> Web >> Angular >> Select Angular Component. Provide component name and click on Add button.
After that, it will open a new “Add new Angular Component” window.
It uses the default naming convention and provides multiple checkboxes for the choice of the Folder name, template name, class file name, test file name, style file name. Drop-Down list for stylesheet languages like CSS, SCSS, and LESS.
If you want a customized name, then you can provide the customized name as well for that just checked in the “Use custom names” checkbox. Following is a screenshot of the same.
Click on Add to proceed. It will take a while, and after that, it will add all the required files. Go to solution explorer and open the customer folder. You can see all the newly added files along with customer folder.
Newly Added Component
Add navigation and routing data.
Changes for routing in app.shared.module.ts
Go to the file app.shared.module.ts and make changes as shown in the following screenshot.
Changes for Navigation in navmenu.component.html
Open the file navmenu.component.html and add following lines
- <li [routerLinkActive]="['link-active']">
- <a [routerLink]="['/customer']">
- <span class='glyphicon glyphicon-user'></span> Customer
- </a>
- </li>
Now run the application and click on the customer link provided in the left menu.
You can see that it is displaying the default generated text which proves that navigation and routing functionalities are working fine.
Display JSON data from a *.ts file
You can see that Navigation and routing are working fine for customer component and now for the newly added customer component we will display the data from a *.ts file. Means I am going to display the dummy data rather than calling an API service to get real data from a database.
- Add a class “customer.ts”
- Add a new file “customerdata.ts”
- Open “customer.ts” file and add properties inside the customer class
- export class customer {
- id: number;
- firstName: string;
- lastName: string;
- email: string;
- gender: string;
- city: string;
- country: string;
- }
- Open “customerdata.ts” file and import customer and add some dummy data.
- import { customer } from '../class/customer';
-
- export const CUSTOMERS: customer[] = [
- { "id": 1, "firstName": "Bobbette", "lastName": "Wignall", "email": "[email protected]", "gender": "Female", "city": "Bochum", "country": "Germany" },
- { "id": 2, "firstName": "Christine", "lastName": "ducarme", "email": "[email protected]", "gender": "Female", "city": "Makariv", "country": "Ukraine" },
- { "id": 3, "firstName": "Geralda", "lastName": "Byart", "email": "[email protected]", "gender": "Female", "city": "Thị Xã Lai Châu", "country": "Vietnam" },
- { "id": 4, "firstName": "Brynna", "lastName": "Couronne", "email": "[email protected]", "gender": "Female", "city": "Ciudad del Este", "country": "Paraguay" },
- { "id": 5, "firstName": "Nikoletta", "lastName": "Hatchette", "email": "[email protected]", "gender": "Female", "city": "Utmānzai", "country": "Pakistan" },
- { "id": 6, "firstName": "Darell", "lastName": "Foxhall", "email": "[email protected]", "gender": "Female", "city": "Daqiao", "country": "China" },
- { "id": 7, "firstName": "Glynda", "lastName": "McCrystal", "email": "[email protected]", "gender": "Female", "city": "Izumi", "country": "Japan" },
- { "id": 8, "firstName": "Britteny", "lastName": "Broy", "email": "[email protected]", "gender": "Female", "city": "Mazhu", "country": "China" },
- { "id": 9, "firstName": "Milt", "lastName": "Riceards", "email": "[email protected]", "gender": "Male", "city": "Cavalões", "country": "Portugal" },
- { "id": 10, "firstName": "Josselyn", "lastName": "Kinlock", "email": "[email protected]", "gender": "Female", "city": "Wulan", "country": "China" },
- { "id": 11, "firstName": "Erick", "lastName": "Gheeraert", "email": "[email protected]", "gender": "Male", "city": "Heshe", "country": "China" },
- { "id": 12, "firstName": "Riobard", "lastName": "Tarrant", "email": "[email protected]", "gender": "Male", "city": "Besisahar", "country": "Nepal" },
- { "id": 13, "firstName": "Langsdon", "lastName": "Gerardi", "email": "[email protected]", "gender": "Male", "city": "Cikaso", "country": "Indonesia" },
- { "id": 14, "firstName": "Thaine", "lastName": "Brann", "email": "[email protected]", "gender": "Male", "city": "Nizhneivkino", "country": "Russia" },
- { "id": 15, "firstName": "Collie", "lastName": "Dewes", "email": "[email protected]", "gender": "Female", "city": "Rettikhovka", "country": "Russia" },
- { "id": 16, "firstName": "Donny", "lastName": "Ingleson", "email": "[email protected]", "gender": "Female", "city": "Villasis", "country": "Philippines" },
- { "id": 17, "firstName": "Vinita", "lastName": "Dowles", "email": "[email protected]", "gender": "Female", "city": "Santo Tomas", "country": "Philippines" },
- { "id": 18, "firstName": "Bil", "lastName": "Rowan", "email": "[email protected]", "gender": "Male", "city": "Huangtian", "country": "China" },
- { "id": 19, "firstName": "Yardley", "lastName": "Lambdean", "email": "[email protected]", "gender": "Male", "city": "Beisijiazi", "country": "China" },
- { "id": 20, "firstName": "Renell", "lastName": "Valentinetti", "email": "[email protected]", "gender": "Female", "city": "Gayam", "country": "Indonesia" }
- ]
- Open “customer.component.html” file and write following HTML code inside this file.
- <h1>Customer Details</h1>
-
- <table class='table' *ngIf="customers">
- <thead>
- <tr>
- <th>Id</th>
- <th>Name</th>
- <th>Email</th>
- <th>Gender</th>
- <th>City</th>
- <th>Country</th>
- </tr>
- </thead>
- <tbody>
- <tr *ngFor="let customer of customers">
- <td>{{ customer.id}}</td>
- <td>{{ customer.firstName + " " + customer.lastName}}</td>
- <td>{{ customer.email }}</td>
- <td>{{ customer.gender }}</td>
- <td>{{ customer.city }}</td>
- <td>{{ customer.country }}</td>
- </tr>
- </tbody>
- </table>
Following is a screenshot of the same.
Have a look at the highlighted code in the following screenshot as I am going to explain some important concepts.
*ngIf
<table class='table' *ngIf="customers">
It will remove the entire element if provided expression become false. So, in the above scenarios if “customers” variable is null or undefined then it will hide the entire table.
*ngFor
<tr *ngFor="let customer of customers">
*ngFor is a repeater directive which repeats the host element for each element in the list. In the above example host element is <tr> so it will generate 20 <tr> because “customers” variable have 20 elements in the list.
Writing multiple elements in interpolation
<td>{{ customer.firstName + " " + customer.lastName}}</td>
As you can see that <td> for Name is using multiple variables and it has been concatenated which shows that we can use more than one element in interpolation.
Running the application and see the out after add dummy data
The task for adding dummy data for customers has been done, and now we can see the output on the UI screen so re-run the application if you have stopped it. If your application was running already just go to the browser and navigate to customer page, you do not need to re-build the application the web page should refresh and display the latest data automatically. Following is the screenshot of UI for customer page.
Apply Paging using “ngx-pagination”
You can see in the above screenshot that all data are being displayed but need to scroll down to see the complete data. Right now, we have only 20 customers, but in the live application, we may have hundreds of customers so we can use paging to display data.
There are multiple plugins available for Paging, and you can choose any one of then based on your requirements. Right now, I am going to use “ngx-pagination”.
Installing npm package with Visual Studio 2017
There are multiple ways to install an npm package with Visual Studio 2017, but I am going to explain only 3 favorite ways to install an NPM package with Visual Studio 2017.
Installing an NPM package through Quick package install.
In Visual Studio 2017 we have an option for installing “NuGet” & “Bower” packages by default as shown in the following screenshot.
However, there is no option provided by default to manage npm packages. However, we can add options for managing npm packages as well with Visual Studio 2017.
Download, a Visual Studio Extension, called “Package Installer” from here.
Download and install the package this package. Once it is completed, you can see a similar screen as shown below.
Re-open the application with Visual Studio 2017 >> Solution Explorer >> Select the Project >> Right click on it. Now you can see that there is an option available for “Quick Install Package…” or you can press the shortcut “Shift + Alt + 0”.
It will open the “Quick Install Package” window using which you can install npm, Bower, JSPM, NuGet, TSD, Typings and Yarn.
Installing an NPM package through “Open Command Line”.
Open Command Line is another option by using which we can install npm packages.
Go to Tool menu >> Extensions and Updates… >> search for Open Command Line
Download and install this extension. Once This installation is completed then re-open your project and go to “package.json” file. Right click on it and select “Open Command Line”. It will open a new command line window.
However, each time you do not need to go to package.json file and then open the command line window. You can open it by just using the shortcut “Alt + Space” from anywhere in the project.
Getting an NPM package By making changes in the package.json file.
We can install npm package through command line window, but I have noticed that many packages are failing to install correctly for Angular 4/5 while using it with Visual Studio 2017. There are some dependencies which have been renamed in Angular 4/5.
Go to “package.json”file and directly mention the name of the package which you would like to install and re-build it.
However, getting an npm package by editing “package.json” file is a manual process and must be aware that which package would like to keep in which place. You can see that most of the package name has been mentioned in "devDependencies" section whereas I have added "ngx-pagination" inside "dependencies" section.
Making changes for Pagination
Now re-build the application (it will restore npm packages automatically during the build) to check if everything is working fine.
Changes for app.shared.module.ts
Once "ngx-pagination" is installed make other required changes to run pagination properly.
- Open “app.shared.module.ts” and add following line
- import { NgxPaginationModule } from 'ngx-pagination';
add “NgxPaginationModule” inside “@NgModule.Imports” section.
Changes for customer.component.html
- Open “customer.component.html” and add following lines.
- <tr *ngFor="let customer of customers | paginate: { itemsPerPage: 10, currentPage: p }">
- <pagination-controls (pageChange)="p = $event"></pagination-controls>
The changes have been highlighted in the screenshot as well.
Changes for customer.component.ts
- Open “customer.component.ts” and
Refresh the application.
Getting Data from API Service
Till now we have added data by using a mock file, but now I am going make changes in the customer component to get data from API Service.
Writing code for Web API Controller “CustomerController”.
Create a Web API Controller “CustomerController” and now return data from API service
- using System.Collections.Generic;
- using System.Linq;
- using Microsoft.AspNetCore.Mvc;
-
- namespace AngularFundamental.Controllers
- {
- [Produces("application/json")]
- [Route("api/Customer")]
- public class CustomerController : Controller
- {
- [HttpGet("[action]")]
- public IEnumerable<Customer> GetCustomers()
- {
- return Customers();
- }
-
- private List<Customer> Customers()
- {
-
-
- }
- }
-
- public class Customer
- {
- public int Id { get; set; }
- public string FirstName { get; set; }
- public string LastName { get; set; }
- public string Email { get; set; }
- public string Gender { get; set; }
- public string City { get; set; }
- public string Country { get; set; }
- }
-
- }
Code Changes for customer.component.ts
Now go to the file “customer.component.ts” and change the code.
- Write below code in the import section
- import { Component, Inject } from '@angular/core';
- import { Customer } from '../../class/customer';
- import { Http } from '@angular/http';
I am writing “Inject”, “Customer” and “Http” in the import section because later on, I am going to use it.
- Comment the below lines as no longer I am going to use “CUSTOMERS” constant.
- Create a new array of type Customer.
- public customers: Customer[];
- From the constructor call the API service.
- constructor(http: Http, @Inject('BASE_URL') baseUrl: string) {
- http.get(baseUrl + 'api/Customer/GetCustomers').subscribe(result => {
- this.customers = result.json() as Customer[];
- }, error => console.error(error));
- }
Complete code for customer.component.ts
- import { Component, Inject } from '@angular/core';
- import { Customer } from '../../class/customer';
- import { Http } from '@angular/http';
-
-
-
- @Component({
- selector: 'app-customer',
- templateUrl: './customer.component.html',
- styleUrls: ['./customer.component.css']
- })
-
- export class CustomerComponent {
-
- p: number = 1;
-
- public customers: Customer[];
- constructor(http: Http, @Inject('BASE_URL') baseUrl: string) {
- http.get(baseUrl + 'api/Customer/GetCustomers').subscribe(result => {
- this.customers = result.json() as Customer[];
- }, error => console.error(error));
- }
-
- }
Now re-run the application and navigate to the customer.
You can see that now, the data is coming from the API service and earlier we had only 20 records from a mock data, but right now, I am getting 50 records from an API service thus a total number of pages has been increased to 10 as we are displaying 5 records per page. In this application have used a very simple example for API service but if you would like to explore more about web API service or would like to write a well-designed API service, then please go through the below articles,