使用Angular和Ignite UI for Angular,创建跨平台应用程序的第二部分
上次我做了一个简单的可以进行增删改查操作的应用程序,但这一次我会在此基础上做一些改动。我边做边写,所以不知道最后会变成什么样。
从菜单中使用多个功能
目前只是从用户列表中进行各种操作,但我们还在考虑添加其他功能。
使用导航菜单
使用Ignite UI的NavDrawer功能,可以创建一个从左右两侧弹出的菜单,来进行实现。
首先,我们要添加一个模块。该模块的名称是NavigationDrawerModule,虽然它不是以Igx开头,但是根据GitHub的Issue,它很快会变成IgxNavigationDrawerModule。
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
// Ignite UI モジュールの参照
import {
IgxNavbarModule, IgxIconModule, IgxScrollModule, IgxAvatarModule,
IgxLabelModule, IgxInput, IgxDatePickerModule, IgxButtonModule, IgxRippleModule,
IgxToastModule, IgxDialogModule, IgxCheckboxModule, IgxSwitchModule, IgxSliderModule,
IgxRadioModule, NavigationDrawerModule } from 'igniteui-angular/main';
// Hammer
import "hammerjs";
import { ListComponent } from './list/list.component';
import { DetailComponent } from './detail/detail.component';
import { UserService } from './user/user.service';
import { NewComponent } from './new/new.component';
@NgModule({
declarations: [
AppComponent,
ListComponent,
DetailComponent,
NewComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
AppRoutingModule,
FormsModule,
IgxNavbarModule, // Ignite UI Navbar モジュールの追加
IgxIconModule, // Ignite UI Icon モジュールの追加
IgxScrollModule, // Ignite UI Scroll モジュールの追加
IgxAvatarModule, // Ignite UI Avatar モジュールの追加
IgxLabelModule, // Ignite UI Label モジュールの追加
IgxInput, // Ignite UI Input の追加
IgxDatePickerModule, // Ignite UI DatePicker モジュールの追加
IgxButtonModule, // Ignite UI Button モジュールの追加
IgxRippleModule, // Ignite UI Ripple モジュールの追加
IgxToastModule, // Ignite UI Toast モジュールの追加
IgxDialogModule, // Ignite UI Dialog モジュールの追加
IgxCheckboxModule, // Ignite UI Checkbox モジュールの追加
IgxSwitchModule, // Ignite UI Switch モジュールの追加
IgxSliderModule, // Ignite UI Slider モジュールの追加
IgxRadioModule, // Ignite UI Slider モジュールの追加
NavigationDrawerModule // Ignite UI Drawer モジュールの追加
],
providers: [UserService], // サービスをプロバイダに追加
bootstrap: [AppComponent]
})
export class AppModule { }
2. 我们将菜单添加到app模块中。我们将在添加侧边栏和点击菜单按钮时切换侧边栏。请注意,将pinThreashold设置为false是因为在屏幕尺寸大于1024的情况下,无法获得菜单以外的部分变为灰色的效果。另外,我们删除了app-list。
<igx-navbar [title]="title" actionButtonIcon="menu" (onAction)="drawer.toggle()">
<igx-icon name="add" (click)="onClickAdd()"></igx-icon>
</igx-navbar>
<!-- ドロワーの追加 -->
<igx-nav-drawer #drawer [pinThreshold]="false" width="280px">
<div class="ig-drawer-content">
<nav class="nav">
<!-- ヘッダー -->
<span class="nav-item header">menus</span>
<!-- メニューの追加 -->
<span class="nav-item" [routerLinkActive]="'active'" routerLink="/">
<igx-icon fontSet="material" name="list"></igx-icon>
<span>List</span>
</span>
<span class="nav-item" [routerLinkActive]="'active'" routerLink="grid">
<igx-icon fontSet="material" name="grid_on"></igx-icon>
<span>Grid</span>
</span>
</nav>
</div>
</igx-nav-drawer>
<router-outlet></router-outlet>
因为默认情况下不会以巧妙的样式显示,所以添加 CSS。我们直接使用了 GitHub 的 CSS。导航抽屉的项目和 CSS 不在导航抽屉文件夹中,而是在 app.component 级别上。
.ig-drawer-content {
background: #fff;
}
.ig-drawer-content ::-webkit-scrollbar {
width: 3px;
background: #e4e4e4;
}
.ig-drawer-content ::-webkit-scrollbar-thumb {
background: #ec6f74;
border-radius: 0;
}
.nav {
position: absolute;
width: 100%;
height: 100%;
border-right: 1px solid #e4e4e4;
overflow-y: scroll;
overflow-x: hidden;
}
.nav-item {
display: flex;
flex: 1 0 100%;
flex-flow: row nowrap;
color: #383838;
max-height: 48px;
padding: 12px 16px;
cursor: pointer;
font-size: 14px;
align-items: center;
font-weight: 600;
user-select: none;
outline: transparent;
white-space: nowrap;
}
.nav-item.active {
background-color: #fcc5de;
}
.nav-item:hover {
background-color: #f0f0f0;
}
.nav-item > * + * {
margin-left: 32px;
}
.nav-item.header {
font-size: 16px;
color: #9c9c9c;
font-weight: 400;
cursor: initial;
}
.nav-item.header:hover {
background-color: transparent;
}
5. 菜单已显示在屏幕顶部,但是从最上方弹出并覆盖了菜单,因此需要添加一些CSS以改变其行为。
/*上記のものに以下を追加 */
igx-nav-drawer >>> .ig-nav-drawer-overlay,
igx-nav-drawer >>> .ig-nav-drawer {
margin-top: 56px;
}
使用Angular的功能对列表进行模块化
目前在 app.module.html 中有列表功能,并通过路由显示详细信息和新建页面。但是在使用其他功能时,列表是不需要的,因此让我们将列表本身模块化。
接下来,在 src/app/list 目录下创建一个 list.module.ts 文件,并添加组件和模块的信息。
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Routes, RouterModule } from '@angular/router';
import { ListComponent } from './list.component';
import { DetailComponent } from './detail/detail.component';
import { NewComponent } from './new/new.component';
// Ignite UI モジュールの参照
import {
IgxIconModule, IgxScrollModule, IgxAvatarModule,
IgxLabelModule, IgxInput, IgxDatePickerModule, IgxButtonModule, IgxRippleModule,
IgxToastModule, IgxDialogModule, IgxCheckboxModule, IgxSwitchModule, IgxSliderModule,
IgxRadioModule
} from 'igniteui-angular/main';
const listRoutes: Routes = [
{
// 親パスと子パスを設定
path: 'list', component: ListComponent, children: [
// detail をパスとして指定したら Detail コンポーネントを表示。idがパラメーター
{ path: 'detail/:id', component: DetailComponent },
// new をパスとして指定したら New コンポーネントを表示
{ path: 'new', component: NewComponent }
]
}
];
@NgModule({
declarations: [
ListComponent,
DetailComponent,
NewComponent
],
imports: [
// ルートモジュールを子パスを含めて登録
RouterModule.forChild(listRoutes),
CommonModule,
FormsModule,
IgxScrollModule, // Ignite UI Scroll モジュールの追加
IgxAvatarModule, // Ignite UI Avatar モジュールの追加
IgxLabelModule, // Ignite UI Label モジュールの追加
IgxInput, // Ignite UI Input の追加
IgxDatePickerModule, // Ignite UI DatePicker モジュールの追加
IgxButtonModule, // Ignite UI Button モジュールの追加
IgxRippleModule, // Ignite UI Ripple モジュールの追加
IgxToastModule, // Ignite UI Toast モジュールの追加
IgxDialogModule, // Ignite UI Dialog モジュールの追加
IgxCheckboxModule, // Ignite UI Checkbox モジュールの追加
IgxSwitchModule, // Ignite UI Switch モジュールの追加
IgxSliderModule, // Ignite UI Slider モジュールの追加
IgxRadioModule, // Ignite UI Slider モジュールの追加
],
exports: [RouterModule]
})
export class ListModule { }
3. 在app.module.ts中添加List模块以使其在应用程序中可用,并且暂时删除只在List模块中使用的Ignite UI模块。※虽然后续可能会再次需要添加,但那将在需要时再做。
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { ListModule } from './list/list.module';
import { AppComponent } from './app.component';
// Ignite UI モジュールの参照
import {
IgxNavbarModule, IgxIconModule, NavigationDrawerModule } from 'igniteui-angular/main';
// Hammer
import "hammerjs";
import { UserService } from './user/user.service';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
AppRoutingModule,
FormsModule,
ListModule,
IgxNavbarModule, // Ignite UI Navbar モジュールの追加
IgxIconModule, // Ignite UI Icon モジュールの追加
NavigationDrawerModule // Ignite UI Drawer モジュールの追加
],
providers: [UserService], // サービスをプロバイダに追加
bootstrap: [AppComponent]
})
export class AppModule { }
通过更改 new 和 detail 的路径,我们将修正受影响的 import 路径。
import { Component, OnInit, ViewChild } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { User, Gender } from '../../models/user';
import { UserService } from '../../user/user.service';
import { IgxLabel, IgxInput, IgxAvatar, IgxToast, IgxDialog, IgxCheckbox, IgxSwitch, IgxSlider, IgxRadio } from 'igniteui-angular/main';
import { Router } from '@angular/router';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-new',
templateUrl: './new.component.html',
styleUrls: ['./new.component.css']
})
export class NewComponent implements OnInit {
constructor(private userService: UserService, private router: Router) {
}
@ViewChild('toast') toast: IgxToast;
public user: User;
public gender: string[];
ngOnInit() {
this.user = new User("", "", 0, null, Gender.Other, 0, true);
// Gender を配列から取得
let genderValues = Object.keys(Gender);
this.gender = genderValues.slice(genderValues.length / 2);
}
public loadImage(input: HTMLInputElement): void {
if (!input.value) {
return;
}
let reader = new FileReader();
// Callback when file read.
reader.onload = () => {
input.value = "";
this.user.image = reader.result;
}
reader.readAsDataURL(input.files[0]);
}
public create() {
this.userService.add(this.user).subscribe(() => {
// 作成したらトーストを出してルートに遷移
this.toast.show();
this.router.navigate([`/`]);
});
}
}
import { Component, OnInit, ViewChild } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { IgxLabel, IgxInput, IgxAvatar, IgxToast, IgxDialog } from 'igniteui-angular/main';
import { UserService } from '../../user/user.service';
import { User } from '../../models/user';
import { Router } from '@angular/router';
@Component({
selector: 'app-detail',
templateUrl: './detail.component.html',
styleUrls: ['./detail.component.css']
})
export class DetailComponent implements OnInit {
@ViewChild('toast') toast: IgxToast;
public user: User;
constructor( private route: ActivatedRoute, private router: Router,private userService: UserService ) {
}
ngOnInit() {
// パラメーターの変更をモニタ
this.route.params.subscribe(params => {
this.userService.getUser(params.id).subscribe(
(user) => {this.user = user;}
);
});
}
public save(){
this.userService.save(this.user).subscribe(()=>{
this.toast.show();
});
}
public delete(){
this.userService.delete(this.user).subscribe(()=>{
this.toast.message = "deleted";
this.toast.show();
this.router.navigate([`/`]);
})
}
}
由于路由更改,new变为/list/new,detail变为/list/detail/:id,因此需要修改各自受影响的部分。
import { Component, OnInit, EventEmitter } from '@angular/core';
import { IgxScroll, IgxScrollEvent, IgxAvatar } from "igniteui-angular/main";
import { User } from '../models/user';
import { UserService } from '../user/user.service';
import { Router } from '@angular/router';
@Component({
selector: 'app-list',
templateUrl: './list.component.html',
styleUrls: ['./list.component.css']
})
export class ListComponent implements OnInit {
constructor(private userService: UserService, private router: Router) {
this.load();
}
public users: User[] = new Array<User>();
public visibleUsers: User[];
public visibleUsersCount: number = 8;
ngOnInit() {
// 変更通知を受け取ったら再度データをロード
this.userService.userUpdateSource$.subscribe(
(user)=>{this.load();}
)
}
public load():void{
// ユーザーをサービスから取得。非同期のため subscribe でデータ受け取り。
this.userService.getUsers().subscribe(
(users) => {
this.users = users;
this.visibleUsers = this.users.slice(0, this.visibleUsersCount);
}
);
}
private onItemSelect(user: User): void {
// list/detail にナビゲート
this.router.navigate([`/list/detail/${user.id}`]);
}
private updateList($event: IgxScrollEvent): void {
this.visibleUsers = this.users.slice($event.currentTop, $event.currentTop + this.visibleUsersCount);
}
}
import { Component, ViewChild, ElementRef } from '@angular/core';
import { User } from './models/user';
import { Router } from '@angular/router';
import { IgxNavbar, IgxIcon, NavigationDrawer } from 'igniteui-angular/main';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
selectedUser: User;
title = 'Ignite Ui App';
constructor(private router: Router) {
}
onClickAdd(){
// list/new を呼び出し
this.router.navigate(['/list/new']);
}
}
6. 在 list.component.html 中加入 router-outlet,并相应地更新CSS。
<igx-scroll #scroll (onScroll)="updateList($event)"
[visibleItemsCount]="visibleUsersCount"
[itemHeight]="70"
[totalItemsCount]="users.length">
<ul class="list">
<li class="list-item" *ngFor="let user of visibleUsers" (click)="onItemSelect(user)">
<igx-avatar class="list-item-image" roundShape="true" src="{{user.image}}"></igx-avatar>
<h5 class="list-item-value">{{user.name}}</h5>
</li>
</ul>
</igx-scroll>
<router-outlet></router-outlet>
.list {
width: 250px;
}
.list-item {
list-style: none;
height: 64px;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
.list-item-image, .list-item-value {
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
}
igx-scroll, router-outlet {
float: left;
}
7. 最后,我们将修正应用层级的路由配置。
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { ListComponent } from './list/list.component';
const routes: Routes = [
// 既定はリストコンポーネントを表示
{ path: '', component: ListComponent }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
确保所有的更改都已保存并且操作没有变化。我们已经广泛地进行了修改,现在将所有内容一次性移动到了列表模块中。
数据网格的使用 de
因为在列表中主要是围绕着记录的操作进行设计,所以网格会灵活地显示用户的一览。由于 Ignite UI 提供了灵活而功能强大的数据网格功能,我们将使用该功能。
1. 由于网格是作为组件而不是模块添加的,因此请执行以下命令。
ng generate component grid
接下来,我们要添加模块。数据网格与以往不同,需要使用 .forRoot()。
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { ListModule } from './list/list.module';
import { AppComponent } from './app.component';
import { GridComponent } from './grid/grid.component';
import { UserService } from './user/user.service';
// Ignite UI モジュールの参照
import {
IgxNavbarModule, IgxIconModule, NavigationDrawerModule,
IgxGridModule, } from 'igniteui-angular/main';
// Hammer
import "hammerjs";
@NgModule({
declarations: [
AppComponent,
GridComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
AppRoutingModule,
FormsModule,
ListModule,
IgxNavbarModule, // Ignite UI Navbar モジュールの追加
IgxIconModule, // Ignite UI Icon モジュールの追加
NavigationDrawerModule, // Ignite UI Drawer モジュールの追加
IgxGridModule.forRoot(), // Ignite UI Grid モジュールの追加
],
providers: [UserService], // サービスをプロバイダに追加
bootstrap: [AppComponent]
})
export class AppModule { }
3. 首先,在 Grid 组件中添加数据表格。我们可以尝试使用数据表格的自动列生成 [autoGenerate] 功能来创建网格。
<igx-grid [data]="users" [autoGenerate]="true" [paging]="true" [perPage]="8">
</igx-grid>
import { Component, OnInit } from '@angular/core';
import { User } from '../models/user';
import { UserService } from '../user/user.service';
@Component({
selector: 'app-grid',
templateUrl: './grid.component.html',
styleUrls: ['./grid.component.css']
})
export class GridComponent implements OnInit {
private users: User[] = new Array<User>();
constructor(private userService: UserService) { }
ngOnInit() {
this.userService.getUsers().subscribe((users) => this.users = users);
}
}
为了能够访问Grid组件,请更新路由。
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { ListComponent } from './list/list.component';
import { GridComponent } from './grid/grid.component';
const routes: Routes = [
// 既定はリストコンポーネントを表示
{ path: '', component: ListComponent },
{ path: 'grid', component: GridComponent }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
当您保存完所有内容后,访问 http://localhost:4200/grid。如果列已经自动生成,则表示成功。
6. 接下来逐个添加列。还可以通过更改头像等改变外观。首先从模块加载开始。
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { ListModule } from './list/list.module';
import { AppComponent } from './app.component';
import { GridComponent } from './grid/grid.component';
import { UserService } from './user/user.service';
// Ignite UI モジュールの参照
import {
IgxNavbarModule, IgxIconModule, NavigationDrawerModule,
IgxGridModule, IgxAvatarModule } from 'igniteui-angular/main';
// Hammer
import "hammerjs";
@NgModule({
declarations: [
AppComponent,
GridComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
AppRoutingModule,
FormsModule,
ListModule,
IgxNavbarModule, // Ignite UI Navbar モジュールの追加
IgxIconModule, // Ignite UI Icon モジュールの追加
NavigationDrawerModule, // Ignite UI Drawer モジュールの追加
IgxGridModule.forRoot(), // Ignite UI Grid モジュールの追加
IgxAvatarModule, // Ignite UI Avatar モジュールの追加
],
providers: [UserService], // サービスをプロバイダに追加
bootstrap: [AppComponent]
})
export class AppModule { }
7. 我们要更改 Grid 组件。我们可以使用 igx-column 来指定列,如果想要更改详细信息,可以使用 Angular 的 ng-template 功能来调整内容。
import { Component, OnInit } from '@angular/core';
import { User } from '../models/user';
import { UserService } from '../user/user.service';
import { IgxIcon, IgxAvatar } from 'igniteui-angular/main';
@Component({
selector: 'app-grid',
templateUrl: './grid.component.html',
styleUrls: ['./grid.component.css']
})
export class GridComponent implements OnInit {
private users: User[] = new Array<User>();
constructor(private userService: UserService) { }
ngOnInit() {
this.userService.getUsers().subscribe((users) => this.users = users);
}
}
<igx-grid #grid [data]="users" [autoGenerate]="false" [paging]="true" [perPage]="6">
<igx-column width="80px" field="userRank" header="Rank" dataType="number" sortable="true"></igx-column>
<igx-column width="120px" field="image">
<ng-template igxCell let-col>
<igx-avatar size="medium" roundShape="true" src="{{col}}"></igx-avatar>
</ng-template>
</igx-column>
<igx-column field="name" header="User Name" dataType="string" editable="true"></igx-column>
<igx-column field="birthdate" header="BirthDate" dataType="Date">
<ng-template igxCell let-col>
{{col.toDateString()}}
</ng-template>
</igx-column>
<igx-column width="120px" field="gender" header="Gender" dataType="Gender"></igx-column>
<igx-column width="120px" field="isAdmin" header="Is Admin" dataType="boolean">
<ng-template igxCell let-col>
<igx-icon *ngIf="col" fontSet="material" name="star" color="red"></igx-icon>
<igx-icon *ngIf="!col" fontSet="material" name="star_border"></igx-icon>
</ng-template>
</igx-column>
</igx-grid>
点击启用排序的Rank标题可以进行排序。另外,双击可编辑的用户名可以更改名称。但请注意,由于此处未添加保存功能,实际上无法使用。
在其他格子中也可以进行搜索。
卡片的使用
使用Ignite UI的卡片功能能够轻松实现瓦片式的用户界面,不同于数据网格和列表的表格形式。
首先,添加一个用于卡片的组件。
ng generate component card
2. 然后添加模块。 .)
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { ListModule } from './list/list.module';
import { AppComponent } from './app.component';
import { GridComponent } from './grid/grid.component';
import { CardComponent } from './card/card.component';
import { UserService } from './user/user.service';
// Ignite UI モジュールの参照
import {
IgxNavbarModule, IgxIconModule, NavigationDrawerModule,
IgxGridModule, IgxAvatarModule, IgxCardModule
} from 'igniteui-angular/main';
// Hammer
import "hammerjs";
@NgModule({
declarations: [
AppComponent,
GridComponent,
CardComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
AppRoutingModule,
FormsModule,
ListModule,
IgxNavbarModule, // Ignite UI Navbar モジュールの追加
IgxIconModule, // Ignite UI Icon モジュールの追加
NavigationDrawerModule, // Ignite UI Drawer モジュールの追加
IgxGridModule.forRoot(), // Ignite UI Grid モジュールの追加
IgxAvatarModule, // Ignite UI Avatar モジュールの追加
IgxCardModule, // Ignite UI Card モジュールの追加
],
providers: [UserService], // サービスをプロバイダに追加
bootstrap: [AppComponent]
})
export class AppModule { }
3. 在路由中添加卡片组件。同时默认为列表,但也允许明确指定为列表。
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { ListComponent } from './list/list.component';
import { GridComponent } from './grid/grid.component';
import { CardComponent } from './card/card.component';
const routes: Routes = [
// 既定はリストコンポーネントを表示
{ path: '', component: ListComponent },
{ path: 'list', component: ListComponent },
{ path: 'grid', component: GridComponent },
{ path: 'card', component: CardComponent }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
4. 为了指定每个用户卡片的图片,需要扩展用户模型。同时在用户服务中设置返回图片的功能。
export class User {
public image: string
public name: string
public id: number
public birthdate: Date
public gender: Gender
public userRank: number
public isAdmin: boolean
public backgroundImage: string
constructor(image: string, name: string, id: number, birthdate: Date,
gender: Gender, userRank: number, isAdmin: boolean, backgroundImage: string ) {
this.image = image;
this.name = name;
this.id = id;
this.birthdate = birthdate;
this.gender = gender;
this.userRank = userRank;
this.isAdmin = isAdmin;
this.backgroundImage = backgroundImage;
}
}
export enum Gender {
Male = 1,
Female,
Other,
}
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { User, Gender } from '../models/user'
import { Subject } from 'rxjs/Subject';
@Injectable()
export class UserService {
private users: Array<User>;
// 通知用に一つ Subject を用意
private userUpdate = new Subject<string>()
public userUpdateSource$ = this.userUpdate.asObservable();
constructor() {
this.users = new Array<User>();
for (let i = 1; i <= 22; i++) {
let birthdate = new Date(2018, 0, i);
let backgrounImage = "http://www.infragistics.com/angular-demos/assets/images/card/media/ny.jpg";
if( i % 4 == 1){
backgrounImage = "http://www.infragistics.com/angular-demos/assets/images/card/media/yosemite.jpg";
}
else if (i%4 == 2){
backgrounImage = "http://www.infragistics.com/angular-demos/assets/images/card/media/monuments.jpg";
}
else if (i%4 == 3){
backgrounImage = "http://www.infragistics.com/angular-demos/assets/images/card/media/the_red_ice_forest.jpg";
}
this.users.push(new User(
`http://www.infragistics.com/angular-demos/assets/images/avatar/${i}.jpg`,
"User: " + i,
i,
birthdate,
Gender.Other,
i,
true,
backgrounImage
));
}
}
getUsers(): Observable<User[]> {
return of(this.users)
}
getUser(id: number): Observable<User> {
return of(this.users.find(x => x.id === +id));
}
add(user: User): Observable<boolean> {
this.users.push(user);
// 追加したことを通知
this.userUpdate.next("updated");
return of(true);
}
save(user: User): Observable<boolean> {
let index = this.users.indexOf(user);
if (index !== -1) {
this.users[index] = user;
return of(true);
}
else {
return of(false);
}
}
delete(user: User): Observable<boolean> {
let index = this.users.indexOf(user);
if (index !== -1) {
this.users.splice(index, 1);
// 削除したことを通知
this.userUpdate.next("updated");
return of(true);
}
else {
return of(false);
}
}
}
5. 更新卡片组件以显示卡片。本次我们仍然直接使用 Ignite UI 控件并指定CSS样式进行自定义。
import { Component, OnInit } from '@angular/core';
import { User } from '../models/user';
import { UserService } from '../user/user.service';
import { IgxAvatar } from 'igniteui-angular/main';
@Component({
selector: 'app-card',
templateUrl: './card.component.html',
styleUrls: ['./card.component.css']
})
export class CardComponent implements OnInit {
private users: User[] = new Array<User>();
constructor(private userService: UserService) { }
ngOnInit() {
this.userService.getUsers().subscribe((users) => this.users = users);
}
private openUrl(url: string): void {
window.location.href = url;
}
}
<div class="card">
<div class="card-item" *ngFor="let user of users">
<igx-card>
<div style="overflow: hidden">
<img width="100%" height="100%" src="{{user.backgroundImage}}">
</div>
<igx-card-header>
<igx-avatar class="list-item-image" roundShape="true" src="{{user.image}}"></igx-avatar>
<h2 class="list-item-value">{{user.name}}</h2>
</igx-card-header>
<igx-card-content>
Rank:{{user.userRank}}
<br/> Birthday: {{user.birthdate.toDateString()}}
</igx-card-content>
<igx-card-actions>
<button igxButton igxRipple>Like</button>
<button igxButton igxRipple>Share</button>
</igx-card-actions>
</igx-card>
</div>
</div>
.card {
display: flex;
flex-flow: row wrap;
}
.card-item{
max-width:400px;
padding:10px;
}
igx-card-header {
background: #f8f8ff;
}
igx-card-content {
background: gray;
color:white;
}
6. 最後,我们会更新导航栏并创建卡片的链接。同时,我们还尝试了选择菜单时关闭导航栏的功能。
<igx-navbar [title]="title" actionButtonIcon="menu" (onAction)="drawer.toggle()">
<igx-icon name="add" (click)="onClickAdd()"></igx-icon>
</igx-navbar>
<!-- ドロワーの追加 -->
<igx-nav-drawer #drawer [pinThreshold]="false" width="280px">
<div class="ig-drawer-content">
<nav class="nav">
<!-- ヘッダー -->
<span class="nav-item header">menus</span>
<!-- メニューの追加 -->
<span class="nav-item" [routerLinkActive]="'active'" routerLink="list" (click)="drawer.close();">
<igx-icon fontSet="material" name="list"></igx-icon>
<span>List</span>
</span>
<span class="nav-item" [routerLinkActive]="'active'" routerLink="grid" (click)="drawer.close();">
<igx-icon fontSet="material" name="grid_on"></igx-icon>
<span>Grid</span>
</span>
<span class="nav-item" [routerLinkActive]="'active'" routerLink="card" (click)="drawer.close();">
<igx-icon fontSet="material" name="view_module"></igx-icon>
<span>Card</span>
</span>
</nav>
</div>
</igx-nav-drawer>
<router-outlet></router-outlet>
将所有更改保存,并在访问 http://localhost:4200/card 时,屏幕会按以下方式进行更新。请确保还测试了菜单的功能。
手机的考虑
当使用手机时,屏幕尺寸会发生改变,但Ignite UI具备响应式功能,可以很灵活地适应不同屏幕尺寸。在手机上有一个有趣的控件,称为Tab Bar。
当进行本地开发时,我认为会结合Ionic等进行开发,不过我们可以在另一个机会再来看看。
概括
我已经查看了Ignite UI,个人而言我很喜欢它。除了Angular版本之外,Ignite UI还有JavaScript版本。此外,似乎还有适用于Xamarin、MVC、WPF、iOS和Android的控件,一旦我尝试过,就会写一篇文章介绍。
请参考
英格拉菲克终极套件:开发工具包总览
英格拉菲克举办的事件。