Glenn Jones

Hello đź‘‹ Welcome to my corner of the internet. I write here about the different challenges I encounter, and the projects I work on. Find out more about me.

Workflow for setting up Elixir Phoenix channel

Channels are an abstraction made to make it easier to work with realtime features in your application. As said in the official docs:

Channels are based on a simple idea - sending and receiving messages. Senders broadcast messages about topics. Receivers subscribe to topics so that they can get those messages. Senders and receivers can switch roles on the same topic at any time.

Me not being used to the abstraction, their manual is very helpful. I recommend you to quickly read through that first. Then, I use the following 4 step process to create & adjust channels.

The code I use in the following paragraphs is taken mostly from the tutorial, with slight adjustments in naming.

1: Set up “routes” for the channel you’re about to make. You do this in lib/app_name/endpoint.ex. You should refer to a particular socket (eg. ChartSocket).

2: In ChartSocket, which is in web/channels/chart_socket.ex, refer to the right channel (eg. ChartChannel). That looks like: elixir channel "charts:*", ElixirYahooChart.ChartChannel

3: Now you’re all set-up to make the client-js. Add the following elements to your landingpage:

<h2>Chartssocket</h2>
<div id="chart-messages"></div>
<input id="chart-chat-input" type="text"></input>

Then add the client-side javascript to connect to the socket, find the right channel and push messages to that channel. Don’t forget to add the .js file in app.js (at the bottom you’ll see examples). I’ve called my file chartsocket.js and added it to app.js with:

import chartsocket from "./chartsocket”

The contents of the file are:

import {Socket} from "phoenix"

let socket = new Socket("/chartsocket", {params: {token: window.userToken}})

socket.connect()

// Now that you are connected, you can join channels with a topic:
let chachannel = socket.channel("charts:lobby", {})

let chatInput         = $("#chart-chat-input")
let messagesContainer = $("#chart-messages")

chatInput.on("keypress", event => {
  if(event.keyCode === 13){
    chachannel.push("new_msg", {body: chatInput.val()})
    chatInput.val("")
  }
})

chachannel.on("new_msg", payload => {
  messagesContainer.append(`<br/>[${Date()}] ${payload.body}`)
})

chachannel.join()
  .receive("ok", resp => { console.log("Joined successfully", resp) })
  .receive("error", resp => { console.log("Unable to join", resp) })

export default socket

4: Then in ChartChannel (located at web/channels/chart_channel.ex), you should add the different handlers on how to deal with messages. Taken straight from the tut:

defmodule ElixirYahooChart.ChartChannel do
  use Phoenix.Channel

  def join("charts:lobby", _message, socket) do
    {:ok, socket}
  end

  def join("charts:" <> _private_room_id, _params, _socket) do
    {:error, %{reason: "unauthorized"}}
  end

  def handle_in("new_msg", %{"body" => body}, socket) do
    broadcast! socket, "new_msg", %{body: body}
    {:noreply, socket}
  end

  def handle_out("new_msg", payload, socket) do
    push socket, "new_msg", payload
    {:noreply, socket}
  end

end

Hope that helps!

Links

Previous: Building my first chrome extension - website-to-api image uploader
Next: Per-controller resource authorization in elixir phoenix