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

时间:2017-10-31 15:42:47

标签: angular

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

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

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

首先点击 enter image description here

第二次点击 enter image description here

客户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);
        this.customers = this.customerService.customers;
    }
}




客户list.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>
&#13;
&#13;
&#13;

customer.service.ts

&#13;
&#13;
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                
        };
    }    
}
&#13;
&#13;
&#13;

致以最诚挚的问候,

凯文

4 个答案:

答案 0 :(得分:3)

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

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

查看更改的代码,这允许组件subscribe到服务返回的observable并从服务中删除状态。这是一种更清洁的方法。如果要跟踪所有客户,请在组件中添加另一个阵列(而不是服务),以便在返回时推送更多客户。

<强>客户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)
            .subscribe(customers => {
                this.customers = customers;
            });
    }
}

<强> 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";
    // No more customers state
    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).map(result => {
            var customers: Customer[] = []
            for (var item of result.json().data) {
                var customer = this.MapCustomerFromResource(item.data);
                customers.push(customer);
            }
            return customers;
        }, 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                
        };
    }    
}

答案 1 :(得分:0)

您不应该将push()方法用于您要实现的目标。这会将数据添加到现有列表中。

me.http.get(url).subscribe(result => {
    for (var item of result.json().data) {
        var customer = me.MapCustomerFromResource(item.data);
        me.customers.push(customer);
    }
}

如果您希望更新客户列表,您应该执行以下操作:

me.http.get(url).subscribe(
    (res) => me.onSuccess(res.json),
    (res) => me.onError(res.json)
);

private onSuccess(data) {
    me.customers = data;
}

private onError(error) {
    this.errorMessage = error.toString();
}

答案 2 :(得分:0)

在开始推送结果之前,您应该清除服务中的customers

答案 3 :(得分:0)

只需在订阅中设置me.customers = []

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 => {
            me.customers = []; // This line will fix that issue.
            for (var item of result.json().data) {
                var customer = me.MapCustomerFromResource(item.data);
                me.customers.push(customer);
            }
        }, error => console.error(error));
    }