Update tabs badge total from a different component


#1

A common scenario is to have a set of tabs at the bottom of a view and then to indicate the number of “whatever” for a particular tab inside a badge.

With ionic 2, if the tabs are in one component/page, and the page with the functionality which impacts the number of “whatever” items for the badge are in a different page, what is the proper way to have communication from the latter page to the tabs page, so that the number of items in the tabs badge dynamically updates?


#2

create a service and use Observables/Subjects for that purpose.

With subjects you can update a value and inform all other parts of your code which are using this subject as an observable.


#3

I have a little familiarity with Angular 2, but that article is going too fast and making too many assumptions for me.

Had more success with the last part of Josh Moroney’s tutorial here, using Events.


#4

yeah but i do not recommend using the ionic events. The team around angular 2 had their reasons to not implement such things ;).

The want to garantuee a easy reproducable dataflow --> so you would use subjects/observables and services.
With events you can trigger any event somewhere in your app. And somehow, somewhere anotherpart is listen to it.

But that is only my opinion :wink:


#5

Do you have any easy exaple?

And one more question, using a SharedService is a good idea? Something like this:

import { EventEmitter, Injectable, Output } from '@angular/core';




@Injectable()
export class SharedService {
  @Output() fire: EventEmitter<any> = new EventEmitter();

   constructor() {
     console.log('shared service started');
   }

   change(newCont: number) {
       debugger;
    console.log('change started'); 
     this.fire.emit(newCont);
   }

   getEmittedValue() {
     return this.fire;
   }

} 

Thx


#6
  • @Output only makes sense on components, not services
  • Stop abusing any
  • Ordinarily in a case like this you would want increment()/decrement() instead of setting the value explicitly
  • getEmittedValue() is poorly named and redundant

#7

Ok, so, what is the practice to update the of tabs.ts from other component?

Thx!


#8

I would suggest following @bengtler’s advice.


#9

Do u have any simple example? I can’t :confused:


#10

I will try to be as simple as possible, example:

tabs.html

...
<ion-tab tabIcon="cart" tabTitle="Cart" [tabBadge]="count$ | async" tabBadgeStyle="danger" [root]="tab3"></ion-tab>
...

tabs.ts

...
count$: Observable<number>;
...
constructor(public navCtrl: NavController,  
     public shoppingService: ShoppingService) {
...
ngOnInit(){  
    this.count$ = this.shoppingService.listSize;
  }

tab3-page.html

...
<button ion-button item-end (click)="addToCart(p)">
...

tab3-page.ts

...
constructor(public navCtrl: NavController, 
    private shoppingService: ShoppingService ){
...

private addToCart(product: ProductInterface){
    this.shoppingService.addItem(product);
}
...

shopping.service.ts

...
  private listSizeSubject: Subject<number>;
  private _listSize: Observable<number>;
...
  constructor(){
...
    this.listSizeSubject = new Subject();
    this._listSize = this.listSizeSubject.asObservable();
  }

  get listSize(){
    return this._listSize;
  }

  public addItem(product: ProductInterface){
    this.products.push(product);
    this.listSizeSubject.next(this.products.length);//next method updates the stream value
  }
...

Basically you use a Service to be used by the different tabs, so you keep your Observable there, and we need to update the sequence stream so we use a Subject object which is an Observable and an Observer.

Note that we are using async pipe so it subscribes to the observable that we passed, the pipe that gets the value out of it.

Hope that helps everyone, it took me awhile, and most of people are using localStorage or Events.