angular - 如何防止 Angular ngFor 将数据追加到当前列表?

标签 angular

我正在使用 Angular 4。客户页面上有一个搜索按钮。如果用户单击此按钮,客户列表将显示在表格中。

我正在尝试使用 *ngFor 将客户列表绑定(bind)到表。但是,当单击搜索按钮时,客户列表将附加到表中的当前数据中。

我的期望是表格清晰并且只显示新数据。 请查看我下面的代码并建议如何解决此问题。非常感谢。

第一次点击 enter image description here

第二次点击 enter image description here

客户列表.component.ts

import { Component } from '@angular/core';
import { Http } from '@angular/http';
import { Customer } from './customer';
import { CustomerService } from './customer.service';

@Component({
    selector: 'customer-list',
    templateUrl: './customer-list.component.html',
    providers: [CustomerService]
})
export class CustomerListComponent {
    public customers: Customer[] = [];
    public searchTerm: string;

    constructor(private customerService: CustomerService) {       
    }

    onSearchClicked(): void {
        this.customerService.searchSimilarCustomers(this.searchTerm);
        this.customers = this.customerService.customers;
    }
}

客户列表.component.html

<div class="row">
    <div class="col-md-6">
        <button class="btn btn-primary" data-toggle="modal" data-target="#customer-detail"><i class="fa fa-plus"></i> Create customer</button>
    </div>
    <div class="col-md-6">
        <form class="form-inline pull-right">
            <div class="form-group">
                <div class="input-group">
                    <input type="text" class="form-control" name="searchTerm" [(ngModel)]="searchTerm" placeholder="Search customer">
                </div>
            </div>
            <button type="submit" class="btn btn-primary" (click)="onSearchClicked()"><i class="fa fa-search"></i> Search</button>
        </form>

    </div>
</div>
<table class="table">
    <thead>
        <tr>
            <th>Id</th>
            <th>Reference</th>
            <th>Last Name</th>
            <th>Middle Name</th>
            <th>First Name</th>            
        </tr>
    </thead>
    <tbody>
        <tr *ngFor="let customer of customers">
            <td>{{ customer.id }}</td>
            <td>{{ customer.reference }}</td>
            <td>{{ customer.lastName }}</td>
            <td>{{ customer.middleName }}</td>
            <td>{{ customer.firstName }}</td>
        </tr>
    </tbody>
</table>

客户.service.ts

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Customer } from './customer';

@Injectable()
export class CustomerService {
    private customersUrl = "http://localhost:60001/api/v1/customers";
    public customers: Customer[] = [];

    constructor(private http: Http) { }

    searchSimilarCustomers(searchTerm: string, page: number = 1, itemsPerPage: number = 10) {
        var me = this;
        if (!searchTerm) {
            searchTerm = "";
        }
        var url = me.customersUrl + `?searchTerm=${searchTerm}&page=${page}&itemsPerPage=${itemsPerPage}`;
        me.http.get(url).subscribe(result => {
            for (var item of result.json().data) {
                var customer = me.MapCustomerFromResource(item.data);
                me.customers.push(customer);
            }
        }, error => console.error(error));
    }    

    private MapCustomerFromResource(data: any): Customer {
        return {
            id: data.id,
            reference: data.attributes.reference,
            firstName: data.attributes.firstName,
            middleName: data.attributes.middleName,
            lastName: data.attributes.lastName,
            gender: data.attributes.gender                
        };
    }    
}

最诚挚的问候,

凯文

最佳答案

me.customers.push <= 服务正在添加到同一个数组中,并且该数组被重用。如果您想跟踪所有客户和您刚刚返回的客户,您必须通过创建 2 秒数组来区分。

此外,我不喜欢您的调用结构,没有明确的关注点分离,这导致您引入难以追踪的逻辑错误。坚持内置的订阅机制,以便您的服务返回数据但无状态(即不跟踪客户)。

查看更改后的代码,这允许组件订阅从服务返回的可观察对象并从服务中删除状态。这是一种更干净的方法。如果您想跟踪所有客户,请在您的组件(而不是服务)中添加另一个数组,在返回时推送更多客户。

customer-list.component.ts

import { Component } from '@angular/core';
import { Http } from '@angular/http';
import { Customer } from './customer';
import { CustomerService } from './customer.service';

@Component({
    selector: 'customer-list',
    templateUrl: './customer-list.component.html',
    providers: [CustomerService]
})
export class CustomerListComponent {
    public customers: Customer[] = [];
    public searchTerm: string;

    constructor(private customerService: CustomerService) {       
    }

    onSearchClicked(): void {
        this.customerService.searchSimilarCustomers(this.searchTerm)
            <em><strong>.subscribe(customers => {
                this.customers = customers;
            });</strong></em>
    }
}

customer.service.ts

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Customer } from './customer';

@Injectable()
export class CustomerService {
    private customersUrl = "http://localhost:60001/api/v1/customers";
    <em><strong>// No more customers state</strong></em>
    constructor(private http: Http) { }

    searchSimilarCustomers(searchTerm: string, page: number = 1, itemsPerPage: number = 10) : Observable<Customer[]> {
        if (!searchTerm) {
            searchTerm = "";
        }

        var url = this.customersUrl + `?searchTerm=${searchTerm}&page=${page}&itemsPerPage=${itemsPerPage}`;
        return this.http.get(url).<em><strong>map(result => {
            var customers: Customer[] = []
            for (var item of result.json().data) {
                var customer = this.MapCustomerFromResource(item.data);
                customers.push(customer);
            }
            return customers;
        }</strong></em>, error => console.error(error));
    }    

    private MapCustomerFromResource(data: any): Customer {
        return {
            id: data.id,
            reference: data.attributes.reference,
            firstName: data.attributes.firstName,
            middleName: data.attributes.middleName,
            lastName: data.attributes.lastName,
            gender: data.attributes.gender                
        };
    }    
}

关于angular - 如何防止 Angular ngFor 将数据追加到当前列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47039325/

相关文章:

Angular Karma 不捕获浏览器

asp.net - 由于错误 : Error: Cannot find module "." at webpackMissingModule,预呈现失败

Angular Material paginator无法设置页面大小

javascript - webpack + Angular 2 (rc5) - 组件未在生产版本中渲染

angular - 如何在 Angular2 中注销时获取新实例/重新加载所有服务

css - 是否可以使用 Angular 2 的 ViewEncapsulation.Native 为不同的 Web 组件设置不同的 "rem"?

Angular:将对象传递给指令

javascript - Angular/Javascript - 隐藏带有 id onclick 的按钮

angular - 在 Angular 2 + Immutable.js 中迭代(使用 *ngFor)

angular - 服务构造函数上的 DI 错误