解开Angular 2书,第1章,例5

时间:2016-09-28 21:02:18

标签: javascript angular typescript

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

这是模板:

<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);
  }
}

每当我在搜索框中输入时,都会调用过滤器并重新呈现列表,但是当我点击&#34;添加&#34;按钮。如果我在搜索框中有内容,&#34;添加&#34;即使搜索框的内容允许显示新项目,按钮也不会导致潜水列表的更改。如何更改代码以便单击&#34;添加&#34;按钮会导致重新显示所显示的潜水列表吗?

1 个答案:

答案 0 :(得分:3)

你有一个纯管道所以

  

它的方法transform只有在检测到纯粹时才会执行   更改为输入值。

对于你的情况

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

输入值将为divessearchBox.value

According to the angular2 guide on pipes:

  

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

  • 添加dive时,数组引用(潜水)不会更改 - 因此不会执行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++]];

第二种方法是使用 impure pipe

@Pipe({name: 'contentFilter', pure: false })