介绍Angular 2的书,第1章,示例5

Unraveling Angular 2 book, Chapter 1, Example 5

本文关键字:1章 示例 介绍 的书 Angular      更新时间:2023-09-26

页面显示了一个潜水列表,它有一个"添加新潜水","清除潜水"和一个搜索框,当你输入时,它会过滤显示的列表。

这是模板:

<div class="container-fluid">
  <h1>My Latest Dives (Angular/TypeScript)</h1>
  <div class="row">
    <div class="col-sm-5">
      <button class="btn btn-primary btn-lg"
        [disabled]="!enableAdd()"
        (click)="addDive()">
          Add new dive
      </button>
      <button class="btn btn-danger btn-lg"
        (click)="clearDives()">
          Clear dives
      </button>
    </div>
    <div class="col-sm-4 col-sm-offset-3">
      <input #searchBox class="form-control input-lg"
        placeholder="Search"
        (keyup)="0" />
    </div>
  </div>
  <div class="row">
    <div class="col-sm-4"
      *ngFor="let dive of dives | contentFilter:searchBox.value">
      <h3>{{dive.site}}</h3>
      <h4>{{dive.location}}</h4>
      <h2>{{dive.depth}} feet | {{dive.time}} min</h2>
    </div>
  </div>
</div>

组件代码:

import {Component} from '@angular/core';
@Component({
  selector: 'divelog',
  templateUrl: 'app/dive-log.template.html'
})
export class DiveLogComponent {
  public dives = [];
  private _index = 0;
  private _stockDives = [
  {
    site: 'Abu Gotta Ramada',
    location: 'Hurghada, Egypt',
    depth: 72,
    time: 54
  },
  {
    site: 'Ponte Mahoon',
    location: 'Maehbourg, Mauritius',
    depth: 54,
    time: 38
  },
  {
    site: 'Molnar Cave',
    location: 'Budapest, Hungary',
    depth: 98,
    time: 62
  }];
  public enableAdd() {
    return this._index < this._stockDives.length;
  }
  public addDive() {
    if (this.enableAdd()) {
      this.dives.push(this._stockDives[this._index++]);
    }
  }
  public clearDives() {
    this.dives = [];
    this._index = 0;
  } 
}
这是过滤器代码:
import {Pipe, PipeTransform} from '@angular/core';
@Pipe({name: 'contentFilter'})
export class ContentFilterPipe implements PipeTransform {
  transform(value: any[], searchFor: string) : any[] {
    if (!searchFor) return value;
    searchFor = searchFor.toLowerCase();
    return value.filter(dive => 
      dive.site.toLowerCase().indexOf(searchFor) >= 0 ||
      dive.location.toLowerCase().indexOf(searchFor) >= 0 ||
      dive.depth.toString().indexOf(searchFor) >= 0 ||
      dive.time.toString().indexOf(searchFor) >= 0);
  }
}

当我在搜索框中输入时,过滤器被调用,列表被重新呈现,但当我点击"添加"按钮时却没有。如果我在搜索框中有一些东西,"添加"按钮不会导致潜水列表的变化,即使搜索框的内容允许显示新项目。如何更改代码,以便单击"添加"按钮将导致重新呈现显示的潜水列表?

你有一个纯管道所以

它的方法transform只会在它检测到一个纯更改为输入值。

适合你的情况

*ngFor="let dive of dives | contentFilter:searchBox.value"

输入值将为divessearchBox.value

根据angular2管道指南:

纯更改是对原始输入值的更改(字符串,数字,布尔值,符号)或更改的对象引用(日期,数组、函数、对象).

  • 当添加dive时,数组引用(dives)不会改变-因此transform方法不会执行。
  • 当某些东西被输入到过滤器输入,searchBox.value确实改变-因此执行transform

所以一个可能的解决方案是每次添加div时总是有一个新的引用数组:

替换:

this.dives.push(this._stockDives[this._index++]);

:

this.dives = this.dives.concat(this._stockDives[this._index++]);

或:

this.dives = [...this.dives, this._stockDives[this._index++]];
第二种方法是使用非纯管道:
@Pipe({name: 'contentFilter', pure: false })