viktor-shmigol / ng2-cable

Connect your Angular(2/4)/ionic(2/3) application with Rails ActionCable
https://ng2-cable-example.herokuapp.com
44 stars 14 forks source link

Different subscribers receiving message from other stream #5

Closed chrisbenseler closed 7 years ago

chrisbenseler commented 7 years ago

My app has an component that can be present multiple times at the same time. On the ngOnInit it subscribes to a channel with a certain id:

this.ng2cable.subscribe('ws://localhost:3000/cable', { channel: 'FeaturesChannel', id: this.feature_id }); I have put some console.log with this.feature_id to be certain that it is different.

The component also 'listens' to what is being broadcasted

this.broadcaster.on('UpdateViewType').subscribe( (message:any) => {
    console.log('updated')
})

My channel subscription is:

class FeaturesChannel < ApplicationCable::Channel
  def subscribed
    stream_from "feature_#{params[:id]}"
  end
end

in some controller from my Rails app, there is: ActionCable.server.broadcast "feature_" + @feature.id.to_s, { feature: @feature, action: 'UpdateRecommendation' }

só, as far as I understand, the ActionCable should broadcast "feature{some id}" only to the streams "feature{some id}", but everyone from this.broadcaster.on('UpdateViewType') is receiving it. If the component have been inserted 3 times, console.log('updated') will appear 3 times.

Is there a bug? Something I'm doing wrong?

viktor-shmigol commented 7 years ago

Hey @chrisbenseler thanks for letting me know about that. So as for me it doesn't seem a bug. For resolve this issue you should do something like this :

import { ActivatedRoute } from '@angular/router';
import { Broadcaster } from 'ng2-cable';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-feature',
  templateUrl: './feature.html'
})

export class Feature implements OnInit {
  constructor(private router: ActivatedRoute,
              private broadcaster: Broadcaster) {
  }

  ngOnInit() {
    this.router.params.subscribe((params) => {
      if (params['id']) {
        this.setListeners(params['id']);
      }
    });
  }

  setListeners(featureId) {
    this.broadcaster.on(`UpdateRecommendation_${featureId}`).subscribe((feature) => {
      console.log(feature)
    })
  }
}

And better way to do broadcast in feature model:

# frozen_string_literal: true
class Feature < ApplicationRecord
  after_create :broadcast #or after_save it's up to you

  private

  def broadcast
    ActionCable.server.broadcast("feature_#{id}", feature: self, action: "UpdateRecommendation_#{id}")
  end
end
chrisbenseler commented 7 years ago

@viktor-shmigol thanks for the explanation! I was wondering that this could be a solution. []s!