StimulusJS & Phoenix Channels


#1

This is probably more of a javascript thing but it’s related to phoenix_html and channels. Is there a way to have the socket join a channel and then reference that same socket in javascript in several spots? I’m playing with using stimulusjs and I’m trying to come up with good organization so that when you are on a page a socket joins a channel and then various other stimulusjs controllers can use that same socket.

So far I have a questionnaire_controller.js like so:

import { Controller } from "stimulus"
import socket from "../socket"

export default class extends Controller {
  connect() {
    console.log("questionnaire controller connected")
    let channel = socket.channel(`questionnaire:${this.questionnaireId}:${this.assessmentId}`)
    channel.join()
      .receive("ok", resp => { console.log('Successfully joined questionnaire channel') })
      .receive("error", resp => { console.error("Unable to join", resp) })
  }

  get assigns() {
    return JSON.parse(this.data.get("assigns"))
  }

  get questionnaireId() {
    return this.assigns.questionnaire_id
  }

  get assessmentId() {
    return this.assigns.assessment_id
  }
}

I’m looking for a way for other controllers to be able to use channel to talk to the backend phoenix application.


#2

You can share objects across controllers by defining methods or properties on an Application subclass and accessing them through this.application in your controllers.

For example, in your application.js file, replace:

import { Application } from "stimulus"

with:

import { Application as BaseApplication } from "stimulus"

class Application extends BaseApplication {
  getChannel() {
    // ...
  }
}

Then, in your controllers, call this.application.getChannel().