Sure, I stripped it down to a minimal example. Hope I didn’t forget anything.
I added more than just the update function for people who end up here in future
Javascript hook in leaflet_map.hooks.js:
let Map = {
mounted(){
const markers = {}
const map = L.map('mapid').setView([51.505, -0.09], 14)
... # functions to create the tile layers etc
this.handleEvent("add_marker", ({lat, lon}) => {
const marker = L.marker(L.latLng(lat, lon))
marker.addTo(map)
})
}
}
export {Map}
Map LiveComponent in leaflet_map.ex:
defmodule LeafletMap do
use Surface.Component
prop positions, :list, default: []
def update(assigns, socket) do
socket = Map.put(socket, :assigns, assigns)
socket =
assigns.positions
|> Enum.reduce(socket, fn {lat, lon}, acc_socket ->
acc_socket
|> push_event("add_marker", %{lat: lat, lon: lon})
end)
IO.inspect socket.private # <-- lists the pushed events as expected
{:ok, socket}
end
def render(assigns) do
~F"""
<div class="ui segment" phx-update="ignore">
<div id="mapid" style={"height: #{@height};"} :hook="Map"></div>
</div>
"""
end
end
end
Map LiveView in plot_positions.ex_:
defmodule PlotPositions do
use Surface.LiveView
def mount(_params, _session, socket) do
positions = #.. read from file or DB
{:ok, socket |> assign(positions: positions)}
end
def render(assigns) do
~F"""
<LeafletMap
positions={@positions}
/>
"""
end
end