$ ng g m project
功能:项目列表显示,增加,修改,删除项目。邀请其它人员加入项目。
单一性原则:希望搭建多个组件,每个组件负责自己的功能。
一、project相关组件
$ ng g c project/project-list 【项目列表组件】
$ ng g c project/project-item 【卡片组件】
$ ng g c project/new-project【新建项目组件,新建项目,或者修改项目时候会有一个对话框。】
$ ng g c project/invite 【邀请组件,邀请其它成员的对话框。】
此时这些组件都会在declarations中。
declarations: [ProjectListComponent, ProjectItemComponent, NewProjectComponent, InviteComponent],
我们希望对话框组件出现在entryComponent中。
import { NgModule } from '@angular/core';
import { SharedModule } from '../shared/shared.module';
import { ProjectListComponent } from './project-list/project-list.component';
import { ProjectItemComponent } from './project-item/project-item.component';
import { NewProjectComponent } from './new-project/new-project.component';
import { InviteComponent } from './invite/invite.component';
import { ProjectRoutingModule } from './project-routing.module'; @NgModule({
declarations: [ProjectListComponent, ProjectItemComponent, NewProjectComponent, InviteComponent],
entryComponents: [NewProjectComponent, InviteComponent],
imports: [ SharedModule,
ProjectRoutingModule
]
})
export class ProjectModule { }
二、ProjectList
循环输出每个项目的item,有一个新增项目item的快速响应的按钮。
<app-project-item *ngFor="let project of projects" [item]="project">
</app-project-item>
<button mad-fab type="button" (click)="openNewProjectDialog()">
<mat-icon>add</mat-icon>
</button>
project-item里的内容应该是projectList项目决定的。
export class ProjectListComponent implements OnInit {
projects = [
{
"name": "企业协作平台",
"desc": "这是一个企业内部项目",
"coverImg": "assets/images/covers/0.jpg"
},
{
"name": "自动化测试项目",
"desc": "这是一个企业内部项目",
"coverImg": "assets/images/covers/2.jpg"
} ];
constructor(private dialog: MatDialog) { } ngOnInit() {
} openNewProjectDialog() {
this.dialog.open(NewProjectComponent);
}
}
三、ProjectItem
应该是卡片类型的。
<mat-card class="example-card">
<mat-card-header>
<mat-card-title>每日佳句</mat-card-title> </mat-card-header>
<img mat-card-image [src]="item.coverImg" alt="项目封面">
<mat-card-content>
{{item.desc}}
</mat-card-content>
<mat-card-actions>
<button>
<mat-icon>note</mat-icon>
<span>编辑</span>
</button>
<button>
<mat-icon>group_add</mat-icon>
<span>邀请</span>
</button>
<button>
<mat-icon>delete</mat-icon>
<span>删除</span>
</button>
</mat-card-actions>
</mat-card>
1、邀请
希望这个组件越笨越好,只显示,不做逻辑处理。
所以projectItem中点击 邀请 按钮,只负责把事件发射出去,让父组件知道,不做处理。
<button mat-button type="button" (click)="onInviteClick()">
<mat-icon>group_add</mat-icon>
<span>邀请</span>
</button> @Output() onInvite = new EventEmitter<void>();
onInviteClick() {
this.onInvite.emit();
}
2、编辑
编辑和新建共用一套组件。
ListItem把编辑事件发射出去。
<button mat-button type="button" (click)="onEditClick()">
<mat-icon>note</mat-icon>
<span>编辑</span>
</button> @Output() onEdit = new EventEmitter<void>();
onEditClick() {
this.onEdit.emit();
}
ProjectList得到编辑事件后lauch新建项目组件,传入title。
<app-project-item *ngFor="let project of projects" [item]="project"
class="card"
(onInvite)="lauchInviteDialog()"
(onEdit)="lauchUpdateDialog()">
</app-project-item> lauchUpdateDialog() {
const dialogRef = this.dialog.open(NewProjectComponent, {
data: { title: '编辑项目' }
});
}
NewProject组件中处理新建和编辑。
import { Component, OnInit, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
import { OverlayContainer } from '@angular/cdk/overlay'; @Component({
selector: 'app-new-project',
templateUrl: './new-project.component.html',
styleUrls: ['./new-project.component.scss']
})
export class NewProjectComponent implements OnInit {
title = '';
theme: string = 'myapp-dark-theme';
constructor(@Inject(MAT_DIALOG_DATA) private data: any,
public dialogRef: MatDialogRef<NewProjectComponent>,
private oc: OverlayContainer) { } ngOnInit() {
console.log(JSON.stringify(this.data));
this.title = this.data.title;
// this.oc.themeClass = this.data.dark ? 'myapp-dark-theme' : 'null';
this.oc.getContainerElement().classList.add(this.theme);
}
onSave() {
this.dialogRef.close('I received your message');
}
}
3,删除
前面过程一样,在Project List中lauch确认对话框
<app-project-item *ngFor="let project of projects" [item]="project"
class="card"
(onInvite)="lauchInviteDialog()"
(onEdit)="lauchUpdateDialog()"
(onDelete)="lauchConfimDialog()">
</app-project-item> lauchConfimDialog() {
const dialogRef = this.dialog.open(ConfirmDialogComponent, {
data: { title: '编辑项目', content: '您确认删除该项目吗?' }
});
}
三、路由
{
path: '', redirectTo: '/login', pathMatch: 'full'
},
{
path:'login',loadChildren:'./login/login.module#LoginModule'
},
{
path:'project',loadChildren:'./project/project.module#ProjectModule'
}
];
四、NewProject
<form>
<h2 md-dialog-title>新建项目</h2>
<div mat-dialog-content>
<mat-form-field class="example-full-width" class="full-width">
<input type="text" matInput placeholder="您的email" style="text-align: right">
</mat-form-field>
<mat-form-field class="example-full-width" class="full-width">
<input type="password" matInput placeholder="您的密码" style="text-align: right">
</mat-form-field>
</div>
<div mat-dialog-actions>
<button type="button" mat-raised-button color="primary">保存</button>
<button type="button" mat-button mat-dialog-close>关闭</button>
</div>
</form>
五、Invite
用AutoComplete完成邀请组员的布局。
<form>
<h2 md-dialog-title>邀请组员:</h2>
<div mat-dialog-content>
<mat-form-field class="example-full-width" class="full-width">
<input type="text" matInput placeholder="组员姓名" [matAutocomplete]="autoMembers" >
<mat-autocomplete #autoMembers="matAutocomplete" [displayWith]="displayUser">
<mat-option *ngFor="let option of filteredOptions" [value]="option">
{{option.name}}
</mat-option>
</mat-autocomplete>
</mat-form-field> </div>
<div mat-dialog-actions>
<button type="button" mat-raised-button color="primary" (click)="onSave()">保存</button>
<button type="button" mat-button mat-dialog-close>关闭</button>
</div>
</form>
displayUser(user: { id: string; name: string }) {
return user ? user.name : ''
}
希望这个组件越笨越好,只显示,不做逻辑处理,涉及逻辑了逻辑代码会非常分散。调试的时候更改的地方会非常多。
所以projectItem中点击 邀请 按钮,只负责把事件发射出去,让父组件知道,不做处理。
所以projectList来处理邀请事件,调起Invite组件。
lauchInviteDialog(){
const dialogRef = this.dialog.open(InviteComponent);
}