1
votes

So I have two not related components and I'm trying to communicate between them using a service and a BehaviorSubject. Everything is cool, data is exchanged, but when i call the service from one of the components, it doesn't trigger change detection on the other component.

So to show what I'm talking about in code:

The service:

import {Injectable, Optional, EventEmitter} from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/add/operator/map';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

import { forEach } from '@angular/router/src/utils/collection';


@Injectable()
export class SbkService {
    items: any = [];

    private _itemsSource = new BehaviorSubject<any>(0);
    items$ = this._itemsSource.asObservable();

    constructor (
            private _localStorageService: LocalStorageService
        ) {}

    storeSelection(item) {
        this.items.push(item);
        this.setLocalStorage();
    }

    removeSelection(selectionId) {
        for (var i = this.items.length-1; i >= 0; i--) {
            if (this.items[i].selectionId == selectionId)
                this.items.splice(i, 1);
        }

        this.setLocalStorage();
        return true;
    }

    getLocalStorage() {
        this.items = this._localStorageService.get('items');
        this._itemsSource.next(this.items);
        return this.items;
    }

    setLocalStorage() {
        this._localStorageService.set('items', this.items);
        this._itemsSource.next(this.items);
        return true;
    }
}

Component 1:

import { Component, OnInit } from '@angular/core';
import { SbkService } from '../../services/sbk.service'

import {Subscription} from 'rxjs/Subscription';

@Component({
  selector: 'app-right-sidebar',
  template: `<ul>
       <li *ngFor="let selection of selections">
           {{selection.name}} 
           <span class="cutom-btn" (click)="remove(selection.selectionId)">
               delete
           </span>
       </li>
  </ul>`,
  styles: []
})
export class RightSidebarComponent implements OnInit {
  selections: any = [];

  subscription:Subscription;

  constructor (
    private _sbkService: SbkService
  ) {
  }

  ngOnInit() {
    this.subscription = this._sbkService.items$
       .subscribe(selections => {
         this.selections = selections })

    this._sbkService.getLocalStorage();
  }

  ngOnDestroy() {
    // prevent memory leak when component is destroyed
    this.subscription.unsubscribe();
  }

  remove(selectionId) {
    this._sbkService.removeSelection(selectionId);
  }
}

Component 2:

import { Component, ViewChild, ElementRef  } from '@angular/core';
import 'rxjs/add/operator/map';
import {forEach} from '@angular/router/src/utils/collection';

import {SbkService} from '../services/sbk.service'

@Component({
  selector: 'app-match-table',
  template: `
    <div (click)="addItem('mumble', 1)">Add mumble</div>
    <div (click)="addItem('ts', 2)">Add ts</div>
    <div (click)="addItem('discord', 3)">Add discord</div>
  `,
  styles: []
})
export class MatchTableComponent {

  constructor(
        private _sbkService: SbkService
       ) {}

  //Place a bet in the betslip
  public addItem = (name, selectionId) => {
    item: Object = {};

    item.selectionId = selectionId;
    item.name = name;

    this._sbkService.storeSelection(item);
  }

}

So, when I click on a div from component 2 (MatchTableComponent) it updates the selections array in component 1 (RightSideBarComponent) but doesn't trigger a change detection, so the sorted list doesn't get updated until i refresh the page. When i click on delete from RightSideBarComponent template, it updates the selections array and triggers the change detection.

How can I make this work? I tried subscribing to an event from SbkService in the AppComponent and from there triggering the setLocalStorage from SbkService, but no luck...

1
Where is sorted list here? - yurzui

1 Answers

2
votes

If I'm not wrong, you should set the next "sequence" on your Observable "items" through your BehaviourSubject.

Could you modify and try this?:

storeSelection(item){
   const itemsAux = this._itemsSource.getValues();
   itemsAux.push(item);
   this._itemsSource.next(itemsAux);
}

setLocalStorage(){
   this._localStorageService('items', this._itemsSource.getValues();
   return true;
}