解开 Angular 2 一书,第 1 章,示例 5 [英] Unraveling Angular 2 book, Chapter 1, Example 5

查看:23
本文介绍了解开 Angular 2 一书,第 1 章,示例 5的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

这是模板:

<h1>我最近的潜水(Angular/TypeScript)</h1><div class="row"><div class="col-sm-5"><button class="btn btn-primary btn-lg"[禁用]="!enableAdd()"(点击)="addDive()">添加新的潜水<button class="btn btn-danger btn-lg"(点击)="clearDives()">清除潜水

<div class="col-sm-4 col-sm-offset-3"><input #searchBox class="form-control input-lg"占位符=搜索"(keyup)="0"/>

<div class="row"><div class="col-sm-4"*ngFor="让潜水潜水| contentFilter:searchBox.value"><h3>{{dive.site}}</h3><h4>{{dive.location}}</h4><h2>{{dive.depth}} 英尺 |{{dive.time}} min

这是组件代码:

从'@angular/core'导入{Component};@成分({选择器:潜水日志",templateUrl: 'app/dive-log.template.html'})导出类 DiveLogComponent {公开潜水 = [];私人_index = 0;私人_stockDives = [{网站:'Abu Gotta Ramada',地点:埃及赫尔格达",深度:72,时间:54},{网站:'庞特马洪',地点:'Maehbourg,毛里求斯',深度:54,时间:38},{地点:莫尔纳洞穴",地点:'布达佩斯,匈牙利',深度:98,时间:62}];公共启用添加(){返回 this._index <this._stockDives.length;}公共添加潜水(){如果 (this.enableAdd()) {this.dives.push(this._stockDives[this._index++]);}}公共 clearDives() {this.dives = [];this._index = 0;}}

这是过滤器代码:

import {Pipe, PipeTransform} from '@angular/core';@Pipe({name: 'contentFilter'})导出类 ContentFilterPipe 实现 PipeTransform {变换(值:任何[],搜索:字符串):任何[] {if (!searchFor) 返回值;searchFor = searchFor.toLowerCase();返回值.filter(dive =>潜水.site.toLowerCase().indexOf(searchFor) >= 0 ||潜水位置.toLowerCase().indexOf(searchFor) >= 0 ||潜水深度.toString().indexOf(searchFor) >= 0 ||潜水时间.toString().indexOf(searchFor) >= 0);}}

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

解决方案

你有一个纯管道所以

<块引用>

它的方法 transform 只有在检测到纯更改为输入值.

对于你的情况

*ngFor="让潜水的潜水| contentFilter:searchBox.value"

输入值将是 divessearchBox.value

根据 angular2 管道指南:

<块引用>

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

所以可能的解决方案之一是每次添加一个 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 })

The page shows a list of dives, it has an "add new dive", "clear dives" and a search box, which filters the displayed list as you type into it.

This is the template:

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

This is the component code:

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

This is the filter code:

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

The filter is getting invoked and the list is getting rerendered whenever I type into the search box, but not when I click "add" button. If I have something in the search box, "add" button does not result in the change of the dive list even though the content of the search box allows the new items to be displayed. How do I change the code so that clicking the "add" button would cause rerendering of the displayed list of dives?

解决方案

You have a pure pipe so

its method transform will be executed only when it detects a pure change to the input value.

For your case

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

the input value will be dives and searchBox.value

According to the angular2 guide on pipes:

A pure change is either a change to a primitive input value (String, Number, Boolean, Symbol) or a changed object reference (Date, Array, Function, Object).

So one of possibles solutions is to have always a new reference array each time a div is added:

Just replace:

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

with:

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

or:

this.dives = [...this.dives, this._stockDives[this._index++]];

Second way to do it working is use impure pipe:

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

这篇关于解开 Angular 2 一书,第 1 章,示例 5的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆