
連更的這幾天的文章,我們已經了解了不少angular的知識點了,這次我們來個小成品。
angualr結合ng-zorro快速且規範的開發一個後台系統。 【相關教學推薦:《angular教學】
系統功能包含下面的內容:
所有的service 使用模擬的資料。
說乾咱就乾。
結合ng-zorro
angular比較流行的ui框架有:
Ant Design相信做前端開發的人兒都比較熟悉了。所以這裡我們結合NG-ZORRO這個框架來做。如果熟悉Vue或React版本的Ant Design ,相信你可以無縫連結啊~

我們重新使用angular-cli產生一個項目ng-zorro 。
添加ng-zorro是很簡單的事情:進入ng-zorro根目錄,執行ng add ng-zorro-antd即可。
當然你也可以執行
npm install ng-zorro-antd添加,不建議。
結合ng-zorro完成後,我們執行專案起來npm run start ,你會在http://localhost:4200的頁面看到下圖內容。

Not Bad, Bro.
配置路由
我們改成hash路由,並添加用戶路由,腳手架都幫我們完事了,我們只要做點小修改。
想法:
先加入頁面user使用者的清單頁面,使用ng-zorro中table元件
使用者的新增與變更頁面可以共用同一個頁面,使用ng-zorro中form元件
頁面刪除功能直接使用彈跳窗提示,使用ng-zorro中modal元件
對ng-zorro元件按需引入
調整路由檔案
依照思路,我們得在ng-zorro引入:
// app.module.ts
import { ReactiveFormsModule } from '@angular/forms';
import { NzTableModule } from 'ng-zorro-antd/table';
import { NzModalModule } 從 'ng-zorro-antd/modal';
import { NzButtonModule } from 'ng-zorro-antd/button';
import { NzFormModule } from 'ng-zorro-antd/form';
import { NzInputModule } from 'ng-zorro-antd/input';
// ...
imports: [ // 是在imports 中添加,而不是declarations 中聲明NzTableModule,
NzModalModule,
NzButtonModule,
NzFormModule,
ReactiveFormsModule,
NzInputModule
],簡單易理解原則,我們這裡不使用children進行路由的嵌套:
// app.routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule, PreloadAllModules } 從 '@angular/router';
import { WelcomeComponent } from './pages/welcome/welcome.component';
import { UserComponent } from './pages/user/user.component';
import { UserInfoComponent } from './pages/user/user-info/user-info.component';
// 相關的路由const routes: Routes = [
{
path: '',
pathMatch: 'full',
redirectTo: '/welcome'
},
{
path: 'welcome',
component: WelcomeComponent
},
{
path: 'user',
component: UserComponent
},
{
path: 'user/add',
component: UserInfoComponent
},
{
path: 'user/edit/:uuid',
component: UserInfoComponent
}
];
@NgModule({
imports: [RouterModule.forRoot(
routes,
{
useHash: true,// 使用hash 模式preloadingStrategy: PreloadAllModules
}
)],
exports: [RouterModule]
})
export class AppRoutingModule { }更改選單
使用鷹架產生的選單與我們需要開發的功能不符合,我們來調整下。
// app.component.html
<nz-layout class="app-layout">
<nz-sider class="menu-sidebar"
nzCollapsible
nzWidth="256px"
nzBreakpoint="md"
[(nzCollapsed)]="isCollapsed"
[nzTrigger]="null">
<div class="sidebar-logo">
<!-- 預設點擊logo 跳到首頁-->
<a routerLink="/welcome">
<img src="https://ng.ant.design/assets/img/logo.svg" alt="logo">
<h1>Ng-Zorro</h1>
</a>
</div>
<ul nz-menu nzTheme="dark" nzMode="inline" [nzInlineCollapsed]="isCollapsed">
<li nz-submenu nzOpen nzTitle="使用者管理" nzIcon="dashboard">
<ul>
<li nz-menu-item nzMatchRouter>
<a routerLink="/user">使用者清單</a>
</li>
</ul>
</li>
</ul>
</nz-sider>
<nz-layout>
<nz-header>
<div class="app-header">
<span class="header-trigger" (click)="isCollapsed = !isCollapsed">
<i class="trigger"
nz-icon
[nzType]="isCollapsed ? 'menu-unfold' : 'menu-fold'"
></i>
</span>
</div>
</nz-header>
<nz-content>
<div class="inner-content">
<router-outlet></router-outlet>
</div>
</nz-content>
</nz-layout>
</nz-layout>選單展示,如果我們需要做權限管理的話,是需要後端配合進行傳值的,然後我們再把相關的權限選單渲染到頁面
替換成上面的程式碼後,得到的基本骨架如下:

完成使用者清單
接下來完成使用者清單的骨架,因為使用了UI框架,我麼寫起來異常的方便:
取得使用者清單
// user.component.html
<nz-table #basicTable [nzData]="list">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<!-- 將取得的資料進行遍歷-->
<tr *ngFor="let data of basicTable.data">
<td>{{data.name}}</td>
<td>{{data.position}}</td>
<td>
<a style="color: #f00;">Delete</a>
</td>
</tr>
</tbody>
</nz-table>我們模擬了一些資料在assets資料夾中user.json :
{
"users": [
{
"uuid": 1,
"name": "Jimmy",
"position": "Frontend"
},
{
"uuid": 2,
"name": "Jim",
"position": "Backend"
}
],
"environment": "development"
}編寫好服務之後,我們呼叫取得使用者的資料:
// user.component.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from 'src/app/services/user.service';
@Component({
selector: 'app-user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.scss']
})
export class UserComponent implements OnInit {
public list: any = []
constructor(
private readonly userService: UserService
) { }
ngOnInit(): void {
if(localStorage.getItem('users')) {
let obj = localStorage.getItem('users') || '{}'
this.list = JSON.parse(obj)
} else {
this.getList()
}
}
// 取得使用者列表getList() {
this.userService.getUserList().subscribe({
next: (data: any) => {
localStorage.setItem('users', JSON.stringify(data.users))
this.list = data.users
},
error: (error: any) => {
console.log(error)
}
})
}
}因為沒有引入後端服務,這裡我們採用localstorage的方式記錄狀態。
上面完成後,我們得到列表資訊如下:

新增使用者和編輯使用者
我們簡單建立個表單,裡面含有的欄位就兩個,分別是name和position 。這兩個功能是公用一個表單的~
我們在html中新增:
// user-info.component.html
<form nz-form [formGroup]="validateForm" class="login-form" (ngSubmit)="submitForm()">
<nz-form-item>
<nz-form-control nzErrorTip="請輸入使用者名稱!">
<input type="text" nz-input formControlName="username" placeholder="請輸入使用者名稱" style="width: 160px;" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control nzErrorTip="請輸入職位!">
<input type="text" nz-input formControlName="position" placeholder="請輸入職位" style="width: 160px;"/>
</nz-form-control>
</nz-form-item>
<button nz-button class="login-form-button login-form-margin" [nzType]="'primary'">確認</button>
</form>頁面長這樣子:

然後就是邏輯的判斷,進行添加或修改。如果是連接帶上uuid的標識,就表示是編輯, show you the codes 。
// user-info.component.ts
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, ParamMap } from '@angular/router';
@Component({
selector: 'app-user-info',
templateUrl: './user-info.component.html',
styleUrls: ['./user-info.component.scss']
})
export class UserInfoComponent implements OnInit {
public isAdd: boolean = true;
public userInfo: any = []
public uuid: number = 0;
validateForm!: FormGroup;
constructor(
private fb: FormBuilder,
private route: ActivatedRoute,
) { }
ngOnInit(): void {
this.userInfo = JSON.parse(localStorage.getItem('users') || '[]')
this.route.paramMap.subscribe((params: ParamMap)=>{
this.uuid = parseInt(params.get('uuid') || '0')
})
// 是編輯狀態,設定標誌符if(this.uuid) {
this.isAdd = false
}
if(this.isAdd) {
this.validateForm = this.fb.group({
username: [null, [Validators.required]],
position: [null, [Validators.required]]
});
} else {
let current = (this.userInfo.filter((item: any) => item.uuid === this.uuid))[0] || {}
// 訊息回填this.validateForm = this.fb.group({
username: [current.name, [Validators.required]],
position: [current.position, [Validators.required]]
})
}
}
submitForm() {
// 若不符合提交,則報錯if(!this.validateForm.valid) {
Object.values(this.validateForm.controls).forEach((control: any) => {
if(control?.invalid) {
control?.markAsDirty();
control?.updateValueAndValidity({ onlySelf: true });
}
})
return
}
// 取得表單的資料const data = this.validateForm.value
// 新增使用者if(this.isAdd) {
let lastOne = (this.userInfo.length > 0 ? this.userInfo[this.userInfo.length-1] : {});
this.userInfo.push({
uuid: (lastOne.uuid ? (lastOne.uuid + 1) : 1),
name: data.username,
position: data.position
})
localStorage.setItem('users', JSON.stringify(this.userInfo))
} else { // 編輯用戶,更新資訊let mapList = this.userInfo.map((item: any) => {
if(item.uuid === this.uuid) {
return {
uuid: this.uuid,
name: data.username,
position: data.position
}
}
return item
})
localStorage.setItem('users', JSON.stringify(mapList))
}
}
}我們先設定一個標誌符isAdd ,預設是新建使用者;當uuid存在的時候,將其設為false值,表示是編輯的狀態,對內容進行表單的回填。提交表單的操作也是依照該標誌符來判斷。我們直接對localStorage的資訊進行變更,以確保同步清單資訊。
刪除功能
我們引入模態對話框進行詢問是否刪除。
// user.component.ts
// 刪除delete(data: any) {
this.modal.confirm({
nzTitle: '<i>你想刪除該使用者?</i>',
nzOnOk: () => {
let users = JSON.parse(localStorage.getItem('users') || '[]');
let filterList = users.filter((item: any) => item.uuid !== data.uuid);
localStorage.setItem('users', JSON.stringify(filterList));
this.list = filterList
}
});
} 
我們找到刪除的數據,將其剔除,重新快取新的用戶數據,並更新table的用戶清單數據。
So,到此為止,我們順利完成了一個簡單的專案。我們用Gif圖整體來看。

【完】