仅在页面刷新后才刷新购物车上的元素数 Angular 8

Number of elements on cart refreshes only after page refresh Angular 8

我正在开发一个简单的购物 MEAN 堆栈应用程序。 在 header 组件上,我有一个带有徽章的购物车,显示用户购物车上的元素数量,当我单击添加到购物车按钮(位于我的产品组件上)时,产品正常添加但数量购物车上的元素仅在我刷新页面时更新。 这是我的 header 模板代码:

<div class="input-group input-group-sm">
                <div class="input-group-append" *ngFor="let p of panier">

                </div>
                        <a class="btn btn-success btn-sm ml-3" *ngIf="isConnected" routerLink="/panier">
                            <!-- <a class="btn btn-success btn-sm ml-3" *ngIf="!isConnected" routerLink="/"></a> -->
                <i class="fa fa-shopping-cart"></i> Cart
                <span class="badge badge-light">{{getSize()}}</span>
            </a>
            </div>

这是我的 header 组件代码:

    import { Component, OnInit, Input } from '@angular/core';
import { AuthentificationService } from '../authentification.service';

import { ProduitsService } from '../produits.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
  user;
  isConnected = false;
  private panier: [];
  size=0; 


  constructor(private AuthService : AuthentificationService,
    private produitsService: ProduitsService) { }


    setSize(quantite){
      this.size+=quantite;
    }
    getSize(){
      console.log(this.panier.length);
     return this.size;
    }

  ngOnInit() {  
    this.AuthService.getUser().subscribe(data =>{


      this.AuthService.getUser().subscribe(data =>{
        console.log(data);
        this.user = data;
        if ( this.user ){ this.isConnected = true;}
        else { this.isConnected = false;}
        console.log("est connecté : " + this.isConnected );
        this.produitsService.getproduitsPanier(this.user).subscribe(data => {
         // console.log("received : " + JSON.stringify(data));
          this.panier = data;
          if (this.panier) //dans le cas où le panier n'est pas encore initialisé
          this.size = this.panier.length; 
          console.log("produits : " + this.panier);
        });

    });



  });


  }



}

这是我的产品组件代码:

    import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ProduitsService } from '../produits.service';
import { AuthentificationService } from '../authentification.service';
import { Observable } from 'rxjs';
import {HomeComponent} from '../home/home.component'

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

export class ProduitsComponent implements OnInit {

  private produits: Object[] = new Array();
  user;
  isConnected = false;
  produitAEnvoyer = {
    "email":"",
    "img" :"",
    "nom" :"",
    "marque" : "",
    "prix" : "",
    "quantite" :""
  };

  constructor(
    private route: ActivatedRoute,
    private produitsService: ProduitsService,
    private AuthService : AuthentificationService,
    private HomeComponent : HomeComponent) {

      }

  ajouterAuPanier(img, nom, marque, prix){


    this.produitAEnvoyer.email = this.user;
    this.produitAEnvoyer.img = img;
    this.produitAEnvoyer.nom = nom;
    this.produitAEnvoyer.marque = marque;
    this.produitAEnvoyer.prix = prix;

    console.log(this.produitAEnvoyer);
    this.produitsService.ajouterAuPanier(this.produitAEnvoyer).subscribe(data => {
      console.log(data);
    })
  }

  updateQuantite(value){
    this.produitAEnvoyer["quantite"] = value;
    console.log("quantite :"+this.produitAEnvoyer.quantite);
  }


  ngOnInit() {

    this.produitsService.getProduits().subscribe(produits =>{

      this.produits = produits;


      for (const p of this.produits) {
        this.produits.sort();
        console.log(JSON.stringify(p));
      }
  });


  this.AuthService.getUser().subscribe(data =>{
    console.log(data);
    this.user = data;
    if ( this.user ){ this.isConnected = true;}
    else { this.isConnected = false;}
    console.log("est connecte : " + this.isConnected+" email :"+this.user);

});


  }

}

编辑 1: 这也是我的产品模板:

    <link href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!------ Include the above in your HEAD tag ---------->

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.8/css/all.css">


<div class="container">


                    <br>  <b><h2 class="text-center">  Catalog of All Our Products ! </h2></b>
                    <hr>

                <br><br>


<div class="card" >
<table class="table table-hover shopping-cart-wrap">
<thead class="text-muted">
<tr>
  <th scope="col">Product</th>
  <th scope="col" width="120">Brand</th>
   <th scope="col" width="120">Price</th>
   <th scope="col" width="120">Quantity</th>
  <th scope="col" width="200" class="text-right">Action</th>
</tr>
</thead>
<tbody *ngFor="let produit of produits">

    <tr>
        <td>
    <figure class="media" >
        <div class="img-wrap"><img src={{produit.img}} class="img-thumbnail img-sm"></div>
        <figcaption class="media-body">
            <h6 class="title text-truncate"> {{produit.nom}} </h6>

        </figcaption>
    </figure> 
    <td> 
        <div class="price-wrap"> 
            <var class="price"> {{produit.marque}} </var> 
        </div> <!-- brand-wrap .// -->
    </td>
    <td> 
        <div class="price-wrap"> 
            <var class="price">USD  {{produit.prix}} $</var> 
            <small class="text-muted">(For 1 quantity)</small> 
        </div> <!-- price-wrap .// -->
    </td>
    <td> 
        <div class="price-wrap"> 
            <input class="form-control" type="number" required (click)="updateQuantite($event.target.value)" min="1" max="20"/> 
        </div> <!-- quantity-wrap .// -->
    </td>
        <td class="text-right" > 
        <a title="" (click)= "ajouterAuPanier(produit.img, produit.nom, produit.marque, produit.prix)" class="btn btn-outline-success" data-toggle="tooltip" data-original-title="Save to Wishlist" > <i class="fa fa-heart" ></i> Add to cart</a> 
        </td>
    </tr>
    <tr>
</tbody>
</table>
</div> <!-- card.// -->

</div> 
<!--container end.//-->

您可以使用 @Input()@Output()EventEmitter 设置父子组件之间的通信,但是由于您已经有了 ProduitService,您可以使用它来共享数据。在您的情况下,项目总数。

在您的 ProduitService 中设置 BehaviorSubject

  total = new BehaviorSubject<number>(0);

  setTotalItems(value: number) {
    this.total.next(value);
  }

然后在您的 ProduitsComponent 中您可以设置值:

this.produitService.setTotalItems(value);

有关有点相关的案例,请参见:

它与我制作的 Stackblitz 相关:https://stackblitz.com/edit/angular-bqxex9

您可以找到使用共享服务在组件之间进行通信的简单实现。

使用ServiceRxjs subject可以解决您的问题。

addremove 按钮被点击时,header 必须被通知某些事件发生并更新最新值。为此 Service 可以用作通信通道。

注意:@input@output只有在组件处于parent-child关系时才能使用。所以对于这种情况,使用服务是最好的选择。

要更新 header 组件中的值,可以使用 Observable

header.component.ts

export class HeaderComponent {
    ...

    ngOnInit() {
        this.appService.getCount().subscribe(count => {
          this.totalItem = count
          }
        );
    }

    ...
}

应用服务

export class AppService {
  count = 0;
  simpleObservable = new Subject();
  simpleObservable$ = this.simpleObservable.asObservable();
  constructor() { }
  addCount() {
    this.count+=1;
    this.simpleObservable.next(this.count)
  }
  removeCount() {
    if (this.count > 0) { this.count-=1 };
    this.simpleObservable.next(this.count)
  }
  getCount(){
    return this.simpleObservable$;
  }
}

Demo