Channel connection issue

Hello,

I created a chart with chart.js to display some data from the application I am working on and I wanted it to update in real time to reflect the changes in the data so I created a chart channel and a socket, but I can’t figure out why it is not working… I’ve been following the guide on elixircast.io and tried to contact the author as well but no reply sofar so I thought I would ask the question here :slight_smile:

so in user_socket.ex I added the channel like so:

channel "chart:*", Assistant.Web.ChartChannel

in chart_channel.ex i modified the generated join function:

def join("chart:title", _payload, socket) do
      {:ok, socket}
  end

in app.js I imported the socket and passed in into my buildChart function:
import socket from “./socket”;

let patientChartElement = document.getElementById("patientChart")
patientChartElement && PatientChart.buildChart(socket);

finally in patient_chart.js i created the chart and added the socket:

import Chart from "chart.js";

let PatientChart = {

    buildChart(socket) {
        var ctx = document.getElementById("patientChart").getContext('2d');
        let patients = document.getElementById("patientChartData").dataset.patients;
        let patients_count = document.getElementById("patientChartData").dataset.count;

        let PatientChart = new Chart(ctx, {
            type: 'bar',
            data: {
                labels: JSON.parse(patients),
                datasets: [{
                    label: '# of Patients by Gender',
                    data: JSON.parse(patients_count),
                    backgroundColor: [
                        'rgba(255, 99, 132, 0.2)',
                        'rgba(54, 162, 235, 0.2)',
                        'rgba(255, 206, 86, 0.2)',
                        'rgba(75, 192, 192, 0.2)',
                        'rgba(153, 102, 255, 0.2)',
                        'rgba(255, 159, 64, 0.2)'
                    ],
                    borderColor: [
                        'rgba(255,99,132,1)',
                        'rgba(54, 162, 235, 1)',
                        'rgba(255, 206, 86, 1)',
                        'rgba(75, 192, 192, 1)',
                        'rgba(153, 102, 255, 1)',
                        'rgba(255, 159, 64, 1)'
                    ],
                    borderWidth: 1
                }]
            },
            options: {
                scales: {
                    yAxes: [{
                        ticks: {
                            beginAtZero:true
                        }
                    }]
                }
            }
        });
        
        this.listenForUpdates(socket, chart);
        
    },

    listenForUpdates(socket, chart){
        let channel = socket.channel("chart:title", {});
        channel.join()
          .receive("ok", resp => { console.log("Joined successfully", resp) })
          .receive("error", resp => { console.log("Unable to join", resp) }) 
          
        channel.on("new_patient", payload => {
            chart.data.dataset.forEach((dataset) => {
                dataset.data = JSON.parse(payload.body);
            });
            chart.update();
        });
    }
};

export default PatientChart;

supposidely when loading the page I should see a console log saying channel joined succesfully or the error but i get nothing… and the chart does not update unless I reload the page.

Probably is something extremely silly but I can’t figure it out :frowning:

Anyhow thanks as always for the help you are all awesome :slight_smile:

-Carlo

Are you absolutely sure you have an element on your page with an ID of patientChart? If that element does not exist, it will not run PatientChart.buildChart(socket).

I think I am yeah otherwise it wouldn’t even display the chart right?

Are you seeing an attempt to join the channel in your Phoenix logs? It should look something along the lines of:

[info] JOIN "chart:title to MyApp.Web.ChartChannel
  Transport:  Phoenix.Transports.WebSocket (2.0.0)
  Serializer:  Phoenix.Transports.V2.WebSocketSerializer
  Parameters: %{}

You say you are getting nothing in your developer console, but you are calling this.listenForUpdates(socket, chart), but you do not seem to have a chart variable. Though, that should be throwing an error when you access that page. Which makes me wonder if your JS is getting compiled.

No I don’t see it in the info :frowning:
it could be the case that it is not getting compiled as I am having tons of issues with brunch honestly

I solved it!!! it was just brunch! Thank you so much for your help :slight_smile:

Although now i get
Uncaught TypeError: Cannot read property ‘forEach’ of undefined
at Object.callback (patient_chart.js:53)
at phoenix.js:619
at Array.map ()
at Channel.trigger (phoenix.js:618)
at phoenix.js:1042
at Array.forEach ()
at phoenix.js:1041
at Socket.decode (phoenix.js:671)
at Socket.onConnMessage (phoenix.js:1027)
at WebSocket.conn.onmessage (phoenix.js:830)

:frowning:

.forEach is not a native JS function. You will need to include a library that gives you that functionality. Unfortunately I am not a frontend person. So I do not know which libraries would give you that.

It is.

chart is undefined when you call this.listenForUpdates(socket, chart). Did you mean PatientChart?

TIL. I swear the last time I look for a for each function, I swear vanilla JS didn’t have it and you needed to pull in jQuery or Lodash or something.

Entirely possible. From what I can gather the first IE version that had support for it was released in 2011 which isn’t exactly early for a function like this. I mention IE because I imagine that was the browser holding everyone back, but I’m not exactly a JS historian, so…

yeah sorry I should have mentioned I had corrected that but still get the error

the error was in this line:

chart.data.dataset.forEach((dataset) => {

It is missing an s in datasets… now I don’t get the error but the chart does not update…

All sorted it works now :slight_smile: There was a problem in my ENdpoint.broadcast_from function :slight_smile: thank you so much for your help and patience

1 Like