网站首页 » 前端开发 » Angular 2+ » Angular 4.x 列表与详情示例(Master/Detail)
上一篇:
下一篇:

Angular 4.x 列表与详情示例(Master/Detail)

在这篇文章中,我们将会做一个英雄列表,并且显示选中英雄的详情。

在开始英雄列表之旅前,请确定你已经有以下文件结构(或者新创建一个项目)。

Angular 2 列表与详情示例

启动服务

运行下面的命令行:

ng serve --open

上面的命令行就是启动服务并运行 应用。这个命令行有几个作用:1.启动应用服务;2.监听文件变化。3.重建APP。

显示 heroes

要想在页面中显示heroes ,你就得添加 heroes 。

创建 heroes

创建一个heroes 数据。

src/app/app.component.ts (hero array)
const HEROES: Hero[] = [
  { id: 11, name: 'Mr. Nice' },
  { id: 12, name: 'Narco' },
  { id: 13, name: 'Bombasto' },
  { id: 14, name: 'Celeritas' },
  { id: 15, name: 'Magneta' },
  { id: 16, name: 'RubberMan' },
  { id: 17, name: 'Dynama' },
  { id: 18, name: 'Dr IQ' },
  { id: 19, name: 'Magma' },
  { id: 20, name: 'Tornado' }
];

HEROES 是一个 Hero 类数组,也就是我们前面定义的 hero 类(Angular 2 入门示例(Hero Editor))。后面会直接从服务器中拿数据,而不用像我们这样手动写个数组。但现在为了方便说明问题,我们还是先来创建一个数组作为模拟数据。

暴露 heroes

在 AppComponent 创建并暴露一个用于绑定数据的公共属性。

app.component.ts (hero array property)
heroes = HEROES;

我们并没有定义 heroes 类型,因为 TypeScript 可以从 HEROES 中推断它是数组类型。

在模板中显示 hero

在模板中显示一个 hero 名单无序列表,在模板中插入下面一段代码:

app.component.html (heroes template)
<h2>My Heroes</h2>
<ul class="heroes">
  <li>
    <!-- each hero goes here -->
  </li>
</ul>

现在你就可以通过这个 HTML 结果来填充数据了。

遍历 heroes

我们的目标就是把一个数组中的 hero 们显示在模板中,你要做的就是遍历并且单独一条条地显示它们。

app.component.html (ngFor)
<li *ngFor="let hero of heroes">

接着我们就可以在 <li> 标签里添加英雄的 id 及名字:

app.component.html (ngFor template)
<li *ngFor="let hero of heroes">
  <span class="badge">{{hero.id}}</span> {{hero.name}}
</li>

保存后,浏览器就可以看到效果了。

英雄的选择

现在应用的英雄列表已经做好了,接下来就是要显示英雄的详细信息。但是目前英雄列表与详情没有联系。我们要实现的效果是当用户选择一个英雄时,就可显示对应英雄的详情信息。

接下来你就要通过一个组件的属性来把点击的英雄以及其详细信息联系起来

处理点击事件

给 <li> 绑定点击事件

app.component.html(template excerpt)
<li *ngFor="let hero of heroes" (click)="onSelect(hero)">
  ...
</li>

Angular 会识别圆括号中的 click 事件。onSelect(hero) 表达式会调用 AppComponent 里的方法。通过传入 hero 对象作为 onSelect 方法的参数。

添加点击处理器

在这里你不再需要 hero 属性,因为你不再是显示一个英雄,而是显示一个英雄列表,但是用户可以点击每一个英雄,因此把下面的代码替换 hero 属性。

src/app/app.component.ts (selectedHero)
selectedHero: Hero;

在默认情况下英雄是没有被选中的,所以你不需要初始化 selectedHero。

添加一个 onSelect() 处理函数来设置 selectedHero 属性的值(保存用户选中的英雄)。

src/app/app.component.ts (onSelect)

onSelect(hero: Hero): void {
  this.selectedHero = hero;
}

模板中的 input 输入框也要绑定 selectedHero

app.component.html (template excerpt)
<h2>{{selectedHero.name}} details!</h2>
<div><label>id: </label>{{selectedHero.id}}</div>
<div>
    <label>name: </label>
    <input [(ngModel)]="selectedHero.name" placeholder="name"/>
</div>

隐藏详情页

通过 ngIf 来隐藏详情页,当页面刚加载完后,selectedHero 还是 undefined 时,当用户点击后 selectedHero  就会被初始化。Angular 不能处理未定义的 selectedHero  属性,并且会抛出异常。

异常

EXCEPTION: TypeError: Cannot read property ‘name’ of undefined in [null]

虽然 selectedHero.name 已经被显示在模板中,但是你必需保证 hero 详情不在 DOM 中显示直到它们被选中。

用一个 <div> 标签把它包起来,并给这个 <div> 添加一个 ngIf  属性,ngIf 的值为 selectedHero 。

src/app/app.component.ts (ngFor)
<div *ngIf="selectedHero">
  <h2>{{selectedHero.name}} details!</h2>
  <div><label>id: </label>{{selectedHero.id}}</div>
  <div>
    <label>name: </label>
    <input [(ngModel)]="selectedHero.name" placeholder="name"/>
  </div>
</div>

内容再一次显示在浏览器中,多么激动人心的时刻。

当还没有选中英雄的时候(selectedHero 未定义,返回 false),ngIf 会从 DOM 中移除详情的 HTML 。当用户选中一个英雄后,selectedHero 就被定义了(保存选中的对象,返回 true)。

注意:ngIf  中的 I 是大写的。

添加选中样式

当选中英雄并显示详情后,我们需要把选中的英雄作高亮处理,以便于跟其它英雄区分开。

在样式文件中添加 selected 样式。然后在模板中给选中的英雄(即是 <li> 标签 )添加 selected  。当用户点击了一个英雄,比如:用户点击了“Magneta”,此时我们就需要给它添加一个 selected 类。

Angular 2 列表与详情示例

注:图片来自官网

在模板中给 <li> 标签绑定 [class.selected]

app.component.ts (setting the CSS class)
[class.selected]="hero === selectedHero"

当表达式(hero === selectedHero) 为true 的时候。Angular 就会给对应的<li> 标签添加 selected 类。当表达式(hero === selectedHero) 为false 的时候,Angular 就会移除 selected 类。

<li *ngFor="let hero of heroes"
  [class.selected]="hero === selectedHero"
  (click)="onSelect(hero)">
  <span class="badge">{{hero.id}}</span> {{hero.name}}
</li>

就像下面这样:

Angular 2 列表与详情示例

源码

app.comonent.html
<h2>My Heroes</h2>
<ul class="heroes">
  <li *ngFor="let hero of heroes" (click)="onSelect(hero)">
    <span class="badge">{{hero.id}}</span> {{hero.name}}
  </li>
</ul>

<div *ngIf="selectedHero">
  <h2>{{selectedHero.name}} details!</h2>
  <div><label>id: </label>{{selectedHero.id}}</div>
  <div>
    <label>name: </label>
    <input [(ngModel)]="selectedHero.name" placeholder="name" />
  </div>
</div>
app.comonent.css
.selected {
  background-color: #CFD8DC !important;
  color: white;
}

.heroes {
  margin: 0 0 2em 0;
  list-style-type: none;
  padding: 0;
  width: 15em;
}

.heroes li {
  cursor: pointer;
  position: relative;
  left: 0;
  background-color: #EEE;
  margin: .5em;
  padding: .3em 0;
  height: 1.6em;
  border-radius: 4px;
}

.heroes li.selected:hover {
  background-color: #BBD8DC !important;
  color: white;
}

.heroes li:hover {
  color: #607D8B;
  background-color: #DDD;
  left: .1em;
}

.heroes .text {
  position: relative;
  top: -3px;
}

.heroes .badge {
  display: inline-block;
  font-size: small;
  color: white;
  padding: 0.8em 0.7em 0 0.7em;
  background-color: #607D8B;
  line-height: 1em;
  position: relative;
  left: -1px;
  top: -4px;
  height: 1.8em;
  margin-right: .8em;
  border-radius: 4px 0 0 4px;
}
app.component.ts

import { Component } from '@angular/core';

export class Hero {
  id: number;
  name: string;
}
const HEROES: Hero[] = [
  { id: 11, name: 'Mr. Nice' },
  { id: 12, name: 'Narco' },
  { id: 13, name: 'Bombasto' },
  { id: 14, name: 'Celeritas' },
  { id: 15, name: 'Magneta' },
  { id: 16, name: 'RubberMan' },
  { id: 17, name: 'Dynama' },
  { id: 18, name: 'Dr IQ' },
  { id: 19, name: 'Magma' },
  { id: 20, name: 'Tornado' }
];

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  title = 'Tour of Heroes';
  heroes = HEROES;
  selectedHero: Hero;
  onSelect(hero: Hero): void {
    this.selectedHero = hero;
  }
}
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms'; // <-- NgModel lives here
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

至此列表页与详情页的 DEMO 就分享到这里。

  • 微信扫一扫,赏我

  • 支付宝扫一扫,赏我

声明

原创文章,不经本站同意,不得以任何形式转载,如有不便,请多多包涵!

本文永久链接:http://yunkus.com/angular-tutorial-part2/

发表评论

电子邮件地址不会被公开。 必填项已用*标注

评论 END