How to execute js function in Drab Commander

What I am doing is this

  1. In Analytics page, I display Chart using Chart.js and stats.
  2. There is 1 chart and 1 stat displayed, but when an user clicks "stat"button in order list, I want to update stat and chart in the page.

So in step 2. I did it to update stats(just simple number) using defhandler. and it updated assigns value so I can see a stat. but chart doesn’t update. because I need to execute Analytics.buildChart() again to update a chart.

That was imported and executed in app.js like this

import AnalyticsChart from "./analytics-chart"
let chartElement = document.getElementById("analyticsChart");
chartElement && AnalyticsChart.buildChart();

So I tried in same defhandler like this.

defhandler show_stats(socket, sender) do
# some code here

poke socket,
            total_sent: total_sent,
            deilvered_count: deilvered_count,
            undelivered_count: undelivered_count,
            total_clicks: total_clicks,
            recent_order: order

socket |> exec_js("AnalyticsChart.buildChart()")

end

And as I expected It doesn’t work.

So how can I do this?

Thanks in advance.

How do you use this assigns? I mean, how AnalyticsChart.buildChart() reads this assigns values?

What is the return value of this exec_js/2?

1 Like

How do you use this assigns? I mean, how AnalyticsChart.buildChart() reads this assigns values?

it reads from html page using javascript like this in analytics-chart.js

import Chart from "chart.js"

let AnalyticsChart = {
  
  buildChart() {
    let ctx = document.getElementById("analyticsChart");
    let labels = ["sent", "delivered", "undelivered", "clicks"];
   
    let total_sent = parseInt(document.getElementById("total-sent").dataset.totalSent);
    let delivered = parseInt(document.getElementById("deilvered-count").dataset.deliveredCount);
    let undelivered = parseInt(document.getElementById("undelivered-count").dataset.undeliveredCount);
    let clicks = parseInt(document.getElementById("total-clicks").dataset.totalClicks);
    let counts = [total_sent, delivered, undelivered, clicks];
    console.log("Is chart working?");
    let chart = new Chart(ctx, {
      type: 'doughnut',
      data: {
        labels: labels,
        datasets: [{
          data: counts,
          backgroundColor: [

            'rgba(54, 162, 235, 0.5)',
            'rgba(255, 206, 86, 0.5)',
            'rgba(255, 99, 132, 0.5)',
            'rgba(75, 192, 192, 0.5)'
          ]
        }] 
      },
      options: {
        
      }
    });
  }
}

export default AnalyticsChart

What is the return value of this exec_js/2?

error] Drab Handler failed with the following exception:
** (Drab.JSExecutionError) AnalyticsChart is not defined
    (drab) lib/drab/exceptions.ex:16: Drab.JSExecutionError.result_or_raise/1
    (drab) lib/drab.ex:323: anonymous fn/7 in Drab.handle_event/6

I just switched to bang version exec_js!/2

1 Like

The values you set in the poke command are the Phoenix assigns. How are they bound to the elements? Like, how is “total_sent” assign bound to the element with ID “total-sent”?

You may use Drab to re-execute JS (see ‘Scripts’ chapter here), but obviously it would work only in the JS parts rendered with templates.

I am guessing that AnalyticsChart is not global? Try to set it up with something like window.AnalyticsChart = AnalyticsChart;

1 Like

The better docs for scripts are here.

2 Likes

The values you set in the poke command are the Phoenix assigns. How are they bound to the elements? Like, how is “total_sent” assign bound to the element with ID “total-sent”?

like this
<p id="total-sent" data-total-sent="<%= @total_sent %>"><%= @total_sent %></p>

then I get the values in js like this

let total_sent = parseInt(document.getElementById("total-sent").dataset.totalSent);
1 Like

Cool, so it should work. Updating the “data-” attribute should update the dataset property as well. You may check it in the console with:

document.getElementById("total-sent").dataset.totalSent

after doing the poke. You just need to find a way to run the update chart function.

3 Likes

Yes, I just found a way to run the update chart function and did it like this in defhandler

socket |> exec_js!("AnalyticsChart.update()")

and it worked.
Thanks!

3 Likes