2016-09-28 17 views
1

該頁面顯示潛水列表,它具有「添加新潛水」,「清除潛水」和搜索框,可在您鍵入內容時對顯示的列表進行過濾。解開Angular 2書,第1章,示例5

這是模板:

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

過濾器是越來越調用,並且列表每次我在搜索框中輸入時都會重新渲染,但當我點擊「添加」按鈕時不會顯示。如果我在搜索框中有東西,即使搜索框的內容允許顯示新項目,「添加」按鈕也不會導致潛水列表的更改。如何更改代碼,以便點擊「添加」按鈕會導致顯示的潛水列表重新渲染?

回答

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