使用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;
}
Capture.PNG

5. 菜单已显示在屏幕顶部,但是从最上方弹出并覆盖了菜单,因此需要添加一些CSS以改变其行为。

/*上記のものに以下を追加 */
igx-nav-drawer >>> .ig-nav-drawer-overlay,
igx-nav-drawer >>> .ig-nav-drawer {
 margin-top: 56px;
}
Capture.PNG

使用Angular的功能对列表进行模块化

目前在 app.module.html 中有列表功能,并通过路由显示详细信息和新建页面。但是在使用其他功能时,列表是不需要的,因此让我们将列表本身模块化。

Capture.PNG

接下来,在 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。如果列已经自动生成,则表示成功。

Capture.PNG

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>
Capture.PNG

点击启用排序的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 时,屏幕会按以下方式进行更新。请确保还测试了菜单的功能。

Capture.PNG

手机的考虑

当使用手机时,屏幕尺寸会发生改变,但Ignite UI具备响应式功能,可以很灵活地适应不同屏幕尺寸。在手机上有一个有趣的控件,称为Tab Bar。

当进行本地开发时,我认为会结合Ionic等进行开发,不过我们可以在另一个机会再来看看。

概括

我已经查看了Ignite UI,个人而言我很喜欢它。除了Angular版本之外,Ignite UI还有JavaScript版本。此外,似乎还有适用于Xamarin、MVC、WPF、iOS和Android的控件,一旦我尝试过,就会写一篇文章介绍。

请参考

英格拉菲克终极套件:开发工具包总览
英格拉菲克举办的事件。

广告
将在 10 秒后关闭
bannerAds