未触发角度变化检测,部分视图层未更新。 ChangeDetectorRef没有解决问题。

时间:2018-02-21 01:13:10

标签: angular local-storage angular-services angular2-changedetection ngzone

我有一个组件:

to_timestamp

利用服务将get()和set()项目添加到localStorage:

import { Component, OnInit, Input, NgZone, ChangeDetectorRef } from '@angular/core';
import { Product } from '../product'; // data types
import { PRODUCTS } from '../mock-products'; // database
import { CartService } from '../cart.service'; // service
import { Subscription } from 'rxjs/Subscription';

@Component({
 selector: 'app-checkout',
 templateUrl: './checkout.component.html',
 styleUrls: ['./checkout.component.css']
 })


export class CheckoutComponent implements OnInit {

 get shoppingCart(): Product[] {
   const result = this.cartService.get();
   return result;
  }
 cartTotal: number;
 @Input() PRODUCTS: Product; 


 constructor(private cartService: CartService, private zone: NgZone, 
   private changeDetectionRef: ChangeDetectorRef) {
     this.cartService.shoppingCart.subscribe((nextValue) => {
     this.changeDetectionRef.detectChanges();
     console.log('nextValue', nextValue); // returns properly
     console.log(`subscribe: ${NgZone.isInAngularZone()}`);  // RETURNS TRUE
});

 }
 ngOnInit() {
  console.log(`ngOnInit: ${NgZone.isInAngularZone()}`); // RETURNS TRUE
  this.estimatedTotal();  // THIS FUNCTION RUNS BUT IS NEVER UPDATED WITH NEW VALUES
  }

 deleteItem(id, shoppingCart) {
  console.log('id to be deleted ' + id.toString());

   const newCart = [];
   for (let i = 0; i < shoppingCart.length; i++) {
     if (shoppingCart[i].id !== id) { 
    newCart.push(shoppingCart[i]); 
    }
  }

this.cartService.set(newCart); 
this.changeDetectionRef.detectChanges(); // THIS DOES NOT SEEM TO BE WORKING AT ALL 
}

  estimatedTotal() {
    const totals = [];
      for (let i = 0; i < this.shoppingCart.length; i++) { // looping through cart
        if (this.shoppingCart != null && this.shoppingCart.length > 0) {
          totals.push(this.shoppingCart[i].price * this.shoppingCart[i].quantity);
          this.cartTotal = totals.reduce((total, amount) => total + amount);
           } else {
            this.cartTotal = 0;
        }
      }
    }

这是HTML:

import { Injectable, NgZone } from '@angular/core';
import { Product } from './product'; // data model
import { PRODUCTS } from './mock-products'; // database +
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { Subject } from 'rxjs/Subject';
import { CartItemComponent } from './cart-item/cart-item.component';
import { CheckoutComponent } from './checkout/checkout.component';

@Injectable()
export class CartService {
 shoppingCart: Subject<Object> = new ReplaySubject<Object>(1);
 constructor() { console.log(`cartService: ${NgZone.isInAngularZone()}`); }

 set(shoppingCart: Product[]) { 
  this.shoppingCart.next(shoppingCart);
  localStorage.setItem('shoppingCart', JSON.stringify(shoppingCart));

 }
 get() {
  return JSON.parse(localStorage.getItem('shoppingCart'));
  }


  }

我遇到的问题是我的UI没有更新 添加,删除新项目或以任何方式更改localStorage(通过cartService)时, {{cartTotal}} 。我认为它可能是区域问题,也许在区域外已经处理了一些更改,并且所有NgZone.isInAngularZone()实例都返回 true 。我订阅了cartService以查看是否可以解决问题,并启动ChangeDetection,这也没有给我想要的结果。然后,我尝试在订阅上强制执行ChangeDetection ,这也不会更新我的 {{cartTotal}} 。我被困在这一天超过一天,任何建议将不胜感激!

2 个答案:

答案 0 :(得分:0)

您调用 estimatedTotal ing ngOnInit ,只有在初始化组件后才会调用一次。所以,cartTotal永远不会更新,这是正常的。

每当购物车更新时都应该调用它,即在this.cartService.shoppingCart.subscribe的订阅方法中

this.cartService.shoppingCart.subscribe((nextValue) => {
     this.estimatedTotal();
}

答案 1 :(得分:0)

大卫的解决方案部分工作,价值会更新,但总是落后一步。我有两个具有兄弟关系的组件相互依赖,我最终重新组合这些组件,他们没有太多的功能。这解决了这个问题!