Angular 4更新关于数组推送的视图 [英] Angular 4 updating view on array push

查看:64
本文介绍了Angular 4更新关于数组推送的视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题似乎很流行,在将新的 element 放入数组后,我尝试了很多次以更新视图,但是没有任何反应.

It looks like this problem is popular, I tried many times to update my view after a new element pushed in my array, but nothing happened.

我将解释我的功能和我想做的事情,并向您展示我的尝试.

I will explain my functions and what I'm trying to do, and I will show you my tries.

我的第一个组件是 car.component.ts ,我曾经使用 carsService 展示了我的汽车列表调用API.

My first component is car.component.ts that I used to show my cars list calling API using carsService.

carsList() {
        this._carsListService.carsService(this.user)
            .subscribe(
                response => {
                        this.result = response;
                        if (this.result.code != 200) {
                             //error response message
                        }
                        else if (this.result.code == 200) {
                            this.data = [] = this.data;
                            this.result.cars.forEach(element => {
                                this.data.push(element);
                            });
                        }
                },
                error => console.log(error)
            );
    }

第二个组件是 insert.component.ts ,我可以添加带有详细信息的新车,carsList应该可以检测到我正在寻找的更改.

Second component is insert.component.ts that I can add a new car with details and the carsList should detect the changes which is what I'm looking for.

insertNew() {
        this._insertService.insertNewService(this.user)
            .toPromise()
            .then(
                response => {
                    this.result = response;
                    if (this.result.status != 200) {
                       //error message
                    } else {
                       // new element inserted and now it is in cars list API
                    }
                },
                error => console.log(error)
            );

    }

现在在我的 car.component.html

 <div *ngFor="let element of data" id="{{element.car_id}}">
    <mat-card>
        <mat-card-content>
          //some details about cars
        </mat-card-content>
    </mat-card>
 </div>

现在一切都适合初读,但是当 insertNew()调用并插入任何新元素时,carsList视图中没有任何变化.

Now everything is fine for first reading, but when insertNew() called and inserted any new element, nothing change in carsList view.

1-我尝试使用 ngZone

carsList() {
            this._carsListService.carsService(this.user)
                .subscribe(
                    response => {
                    this.zone.run(() => { // <==
                            this.result = response;
                            if (this.result.code != 200) {
                                 //error response message
                            }
                            else if (this.result.code == 200) {
                                this.data = [] = this.data;
                                this.result.cars.forEach(element => {
                                    this.data.push(element);
                                });
                            }
                             console.log("using ngzone"); //this console appeared just one time even when I insert anything new
                             });
                    },
                    error => console.log(error)
                );
        }

2-我尝试使用Angular中包含的DoCheck算法,它看起来像将此行< div * ngFor =数据的元素" id ="{{element.car_id}}"> 替换为此÷ ng * ngFor =#element of数据"id =" {{element.car_id}}> ,但Angular说(意外令牌#).

2 - I tried to go with DoCheck algorithm included in Angular, it looks like replacing this line <div *ngFor="let element of data" id="{{element.car_id}}"> with this <div *ngFor="#element of data" id="{{element.car_id}}"> but Angular said (Unexpected token #).

#EDIT

我的服务

carsService(value: Object) {
        return this._appService.LoadAPI(value, this.carsAPI);
    }

LoadAPI

public loadScript(src) {
        let script = document.createElement('script');
        script.type = 'text/javascript';
        document.getElementsByTagName('body')[0].appendChild(script);
        script.src = src;
    }

编辑2

我试图在 insertNew()

constructor( public cars_list: CarComponent)

insertNew() {
            this._insertService.insertNewService(this.user)
                .toPromise()
                .then(
                    response => {
                        this.result = response;
                        if (this.result.status != 200) {
                           //error message
                        } else {
                    this.cars_list.carsList();
                           // new element inserted and now it is in cars list API
                        }
                    },
                    error => console.log(error)
                );

        }

推荐答案

一种方法是创建一个 Observable ,它会在更改时发出您感兴趣的数据.它将在服务内部进行管理,任何必要的组件都可以订阅该 Observable .

One way to do this is to create an Observable that emits the data you're interested in whenever it changes. It would be managed from within a service, and any necessary components can subscribe to that Observable.

当您随后调用 insertNew 时,如果该API调用返回了已添加的项目,则只需将其添加到现有数据中并通知可观察到的对象,而无需进行另一个API调用..

When you then call insertNew, if that API call returns the item that has been added, you can simply add that to your existing data, and notify the observable, without needing to make another API call.

通过让您的组件订阅 Observable ,他们不需要知道何时来获取更新数据,只需将其推送给他们即可.这也意味着无论哪个组件调用该服务,所有组件都将通过可观察的对象接收更新的数据

By having your components subscribe to an Observable, they don't need to know when to get updated data, it's simply pushed to them. It also means that no matter which component calls the service, all components will receive the updated data via the observable

以下是一个说明我的意思的示例:

Here is an example to indicate what I mean:

@Injectable()
export class CarListService {

  const root = 'https://jsonplaceholder.typicode.com';

  // This is your data.
  private data = [];
  // This subject will be used to update the observable
  private _carList = new Subject();

  // This observable is public so that your components can subscribe
  carList$ = this._carList.asObservable();

  constructor(private http: HttpClient) {
    // The notify function emits the data variable out of the observable
    // In it's initial state, it is simply an empty array
    this.notify();
  }

  loadList(): void {
    // Here, we can get our data from the API. Note that this function
    // does not return anything
    this.http.get(this.root + '/users').subscribe((res) => {
      // We update data with what comes back, and call notify again 
      // so that the observable emits the latest data
      this.data = res;
      this.notify();
    })
  }

  insertNew():void {
    // Here we are updating the API
    this.http.post(this.root + "/users", {
      name: "This is my new one"
    }).subscribe((res) => {
      // The API returns our newly created item, so append it to data, and 
      // call notify again to update the observable
      this.data.push(res);
      this.notify();
    })
  }

  private notify() {
    // Call next on the subject with the latest data
    this._carList.next(this.data);
  }
}

如果您想看到它的实际效果,我创建了一个插件来显示我的意思 https://plnkr.co/edit/lLfFcqYqawKcyi3tLtQe?p=preview

If you want to see this in action, I've created a plunker to show what I mean https://plnkr.co/edit/lLfFcqYqawKcyi3tLtQe?p=preview

请注意,服务和组件位于同一文件中,但这仅是示例

Please note that the service and component are in the same file, but that's just for the example

这篇关于Angular 4更新关于数组推送的视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆