简体   繁体   中英

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

I'm working on a simple shopping MEAN stack application. On the header component I have a cart with badge that shows number of elements on the user's cart,when I click on add to cart button (which is situated on my products component), the product is added normally but the number of elements on cart only updates when I refresh the page. This is my header template code :

<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>

This is my header component code:

    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);
        });

    });



  });


  }



}

And this is my product component code:

    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);

});


  }

}

Edit 1: This is also my product template :

    <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.//-->

You could set up the communication between parent and child component using @Input() , @Output() and EventEmitter but as you already have a ProduitService you could use it to share data. In your case the total number of items.

Set a BehaviorSubject in your ProduitService:

  total = new BehaviorSubject<number>(0);

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

Then in your ProduitsComponent you can set the value:

this.produitService.setTotalItems(value);

For a somewhat related case see this: How to communicate with other component in Angular 8 to Add Total

And it's related Stackblitz I made: https://stackblitz.com/edit/angular-bqxex9

The you can find a simple implementation of a communication between components using a shared service.

Using Service and Rxjs subject can solve your problem.

When add or remove button is clicked, the header must be informed that some event occurred and updated the latest value. For that Service can be used as the communication channel.

Note: @input and @output can be used only if components are in the parent-child relationship. So for this case using Service is the best option.

To update the value in the header component Observable can be used.

header.component.ts

export class HeaderComponent {
    ...

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

    ...
}

appService

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM