Angular MVC core ASP.NET Core
▌Introduction
We will start
building the routing with angular 2
router.
▌Environment
▋Visual Studio 2015
Update 3
▋NPM: 3.10.3
▋Microsoft.AspNetCore.Mvc
1.0.0
▋angular 2: 2.1.0
▌MVC : Create new
controller and view
▋Create MVC controller and view
▋Controller
[Area("Basic")]
[Route("Basic/[controller]")]
public class CustomerController : Controller
{
[Route("[action]")]
public IActionResult Index()
{
return View();
}
}
|
▋View
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
|
▌Router
▋Base Url
If
you hadn’t set the base url on _Layout.cshtml, don’t forget it!
<head>
<base href="/">
<!--Skip....-->
</head>
|
▋Enable router
Like we created “Hello world” module and component, we
need to create the following typescripts (under $\wwwroot\app\Basic\Customer,
or other path you may like).
2.
customer.component.ts : our directive.
3.
Customer.main.ts :
bootstrapping and target the browser platform.
▋customer.main.ts
import
{platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {CustomerAppModule} from './customer.app.module';
import {enableProdMode} from '@angular/core';
//enableProdMode();
platformBrowserDynamic().bootstrapModule(CustomerAppModule);
|
▋customer.component.ts
import { Component, OnInit }
from '@angular/core';
import { Routes,
RouterModule } from '@angular/router';
@Component({
selector: 'customer-app',
template: '<router-outlet></router-outlet>'
})
export class CustomerAppComponent implements OnInit {
ngOnInit() {
}
}
|
▋customer.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import {CustomerAppComponent
} from './customer.app.component';
import { RouterModule
} from '@angular/router';
@NgModule({
imports: [
BrowserModule,
HttpModule,
RouterModule.forRoot([]) //The routes should be set here!
],
declarations:
[CustomerAppComponent],
bootstrap:
[CustomerAppComponent]
})
export class CustomerAppModule { }
|
▋/Aears/Basic/Customer/Index.cshtml
Update Index.cshtml to load
/app/Basic/Customer/customer.main.js
and put in the directive: customer-app
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
<hr />
<customer-app>
<div><p><img src="~/images/gif/ajax-loader.gif" /> Please wait ...</p></div>
</customer-app>
@section Scripts
{
<script>
System.config({
map:
{app: 'app/Basic/Customer'},
packages: {app: {main:'customer.main.js',defaultExtension: 'js'}}
});
System.import('app/customer.main').then(null, console.error.bind(console));
</script>
}
|
We will set our routes into RouterModule.forRoot([]) later, now we run the
application and navigate to http://localhost:xxxx/Basic/Customer/Index
We will see an error :
Error:
Cannot match any routes. URL Segment: 'Basic/Customer/Index'
That means the angular router is working but doesn’t
match any route setting because we have not set any yet.
TIPS :
You can set the
default launch url in $\Properties\launchSettings.json
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "Basic/Customer/Index",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}, …
|
▋Create the Single Pages
In
this sample, we will have the following pages :
/Basic/Customer/Index
/Basic/Customer/Create
/Basic/Customer/Update
So
we first create the above components and html and will implement the real
content in the later chapter. For example, the Create component and html should
be looked like this…
▋customer.index.component.ts
import {Component, OnInit} from '@angular/core';
import {Routes} from "@angular/router";
@Component({
selector: 'customer-index',
templateUrl: '/app/Basic/Customer/customer-index.component.html'
})
export class
CustomerIndexComponent implements OnInit {
title:
string;
constructor()
{
this.title = "Customers:Index";
}
ngOnInit() {
}
}
|
▋customer.index.component.html
<h3>{{title}}</h3>
<hr />
<ul>
<li>
<a [routerLink]="['/Basic/Customer/Create']">Go to Create</a>
</li>
<li>
<a [routerLink]="['/Basic/Customer/Edit']">Go to Edit</a>
</li>
</ul>
|
Notice that in [routerLink], the name should be
“/” + “The route path”.
▋Set the routes
Set the routes in RouterModule.forRoot()
and don’t forget to import
the component and declare them!
▋customer.app.module
//Skip...
import {CustomerIndexComponent}
from './customer-index.component';
import
{CustomerCreateComponent} from './customer-create.component';
import
{CustomerEditComponent} from './customer-edit.component';
@NgModule({
imports: [
//Skip...
RouterModule.forRoot([
{ path: 'Basic/Customer/Index', component:
CustomerIndexComponent },
{ path: 'Basic/Customer/Create', component:
CustomerCreateComponent },
{ path: 'Basic/Customer/Edit', component: CustomerEditComponent
},
{ path: '', redirectTo: '/Basic/Customer/Index', pathMatch: 'full' }
])
],
declarations:
[CustomerAppComponent, CustomerIndexComponent,
CustomerCreateComponent, CustomerEditComponent],
bootstrap: [CustomerAppComponent]
})
export class CustomerAppModule { }
|
▋Set the default route if not match any routing
Set
a default route on the last line of routes.
When
the url doesn’t match any route with the routing, it will match the this one.
const appRoutes: Routes = [
{ path: 'Basic/Customer/Index', component: CustomerIndexComponent },
{ path: 'Basic/Customer/Create', component: CustomerCreateComponent },
{ path: 'Basic/Customer/Edit/:id', component: CustomerEditComponent },
{ path: '', redirectTo: '/Basic/Customer/Index', pathMatch: 'full' },
{ path: '**', redirectTo: 'Basic/Customer/Index', pathMatch: 'full' }
];
|
▋The router works now
▌Inject the routes
(Refactoring)
In
latest Angular CLI, it supports creating new project with a default routing
module.
Use the command like this : $> ng new <project name> --routing
And
it’s default being injected to the AppModule!
|
We
will refactor the current route settings and inject them to customer.app.module
from customer.route.
First
create customer.route.ts
▋app/Basic/Customer/customer.app.route.ts
import
{CustomerIndexComponent} from './customer-index.component';
import
{CustomerCreateComponent} from './customer-create.component';
import
{CustomerEditComponent} from './customer-edit.component';
import { ModuleWithProviders
} from '@angular/core';
import { Routes,
RouterModule } from '@angular/router';
const appRoutes:
Routes = [
{ path: 'Basic/Customer/Index', component: CustomerIndexComponent },
{ path: 'Basic/Customer/Create', component: CustomerCreateComponent },
{ path: 'Basic/Customer/Edit', component: CustomerEditComponent },
{ path: '', redirectTo: '/Basic/Customer/Index', pathMatch: 'full' }
];
export const CustomerRoutes:
ModuleWithProviders = RouterModule.forRoot(appRoutes);
|
▋/app/Basic/Customer/customer.app.module.ts
import
{CustomerRoutes} from './customer.route';
@NgModule({
imports: [
BrowserModule,
HttpModule,
CustomerRoutes
],
//Skip...
|
It’s done!
▌Send parameter with
route path
Notice that when we want to edit a customer, we need to
make the Customer Edit Component know which customer we are editing.
There are at least two ways to achieve the goal: Send
customer id to Edit Component.
1.
Thru a Service.
2.
Thru url parameter.
Here we will use url parameter for sending the customer’s
id.
▋Route with parameter
▋app/Basic/Customer/customer.app.route.ts
First update the route of Customer Edit component.
const appRoutes: Routes = [
//…
{ path: 'Basic/Customer/Edit/:id', component: CustomerEditComponent }
];
|
▋app/Basic/Customer/customer-index.route.ts
The event of clicking the [Edit] button is as following.
private editCustomer(item:
Customer) {
this.router.navigate(['Basic/Customer/Edit', item.Id]);
}
|
And the html should be like this,
<input
type="button" class="btn
btn-info" value="Edit" (click)="editCustomer(item)" />
So that when we click the [Edit] button on a customer, we
will navigate to
http://localhost:4240/Basic/Customer/Edit/11
▋Receive route parameter
And how to get the parameter value from Url? The
interface ActivatedRoute
will do us the favor.
▋app/Basic/Customer/customer-edit.component.ts
//...
import {Router, ActivatedRoute} from '@angular/router';
@Component({
selector: 'customer-edit',
providers:
[CustomerService, RestUriService],
templateUrl: '/app/Basic/Customer/customer-edit.component.html'
})
export class CustomerEditComponent
implements OnInit {
//...
constructor(
private router: Router,
private route:
ActivatedRoute,
private custService:
CustomerService) {
//...
}
ngOnInit() {
this.route.params.subscribe(params => {
let custIdValue = params['id'];
let custId =
+custIdValue; //Equales to parseInt
console.log("query id =
" + +custIdValue);
});
}
}
|
▌Start implementing
the content of SPA
We
can now start implementing our content and services of SPA.
But
first, let’s create some fake data and style our pages.
▋Style it
I won’t give much details about the layout of HTML but
focus on the typescripts.
You can take a look at my sample codes in Github.
▋customer.index.component.ts
We will do the following works:
1.
Create const data and use ngFor to display them.
2.
Use router’s navigate function to change current route.
import {Component, OnInit} from '@angular/core';
import {Router} from '@angular/router';
@Component({
selector: 'customer-index',
templateUrl: '/app/Basic/Customer/customer-index.component.html'
})
export class
CustomerIndexComponent implements OnInit {
title:
string;
customers: any[];
constructor(private router:Router) {
this.title = "Customers:Index";
this.customers =
CUSTOMERS;
}
ngOnInit() {
}
//Go to create page
private goToCreate() {
this.router.navigate(['Basic/Customer/Create']);
}
}
const CUSTOMERS: any[] =
[{ "Id": 1, "Name": "<b>JB</b>", "Phone": "0933XXXXXX", "Age": 35 }
//...
];
|
▋customer.index.component.html
<input type="button" class="btn btn-primary" value="Create New" (click)="goToCreate()" />
<!--Skip some html-->
<tr *ngFor="let item of customers; let sn=index">
<td class="col-sm-1 text-center">{{item.Id}}</td>
<td class="col-sm-2" [innerHtml]="item.Name">
</td>
<td class="col-sm-2">{{item.Phone}}</td>
<td class="col-sm-1">{{item.Age}}</td>
<td class="col-sm-2">
<input type="button" class="btn btn-info" value="Edit" (click)="editCustomer(item)" />
<input type="button" class="btn btn-danger" value="Delete" (click)="deleteCustomer(item)" />
</td>
</tr>
|
▋Result
▋What’s next?
In the next
tutorial, we will use the current SPA and build advanced content for our
website.
▌Github
▌Reference
沒有留言:
張貼留言