Bidirectional JS bridge for the native WebView component.
Overview:
Use Dala.UI.webview/1 to embed the component, then call these functions
from handle_info to communicate with the page.
JS Side (injected automatically):
// Send a message to Elixir
window.dala.send({ event: "clicked", id: 42 })
// Receive a message from Elixir
window.dala.onMessage(function(data) { console.log(data) })Elixir Side:
def handle_info({:webview, :message, %{"event" => "clicked", "id" => id}}, socket) do
{:noreply, socket}
end
def handle_info({:webview, :blocked, url}, socket) do
# A navigation attempt was blocked by the allow: whitelist
{:noreply, socket}
endNavigation Functions:
navigate/2- Navigate to URLreload/1- Reload current pagestop_loading/1- Stop loadinggo_forward/1- Go forward in history
Interact Actions:
{:tap, selector}- Tap an element{:type, selector, text}- Type text{:clear, selector}- Clear input{:eval, js_code}- Evaluate JavaScript{:scroll, selector, dx, dy}- Scroll element{:wait, selector, timeout_ms}- Wait for element
Results arrive via:
{:webview, :eval_result, json}- JS eval result{:webview, :interact_result, %{"action" => ..., "success" => ...}}
Summary
Functions
Evaluate arbitrary JavaScript in the current WebView and return the result
asynchronously via handle_info({:webview, :eval_result, result}, socket).
Go forward in the WebView history (if possible).
High-level interact API for driving WebView content programmatically.
Navigate to a new URL in the WebView.
Push a message from Elixir into the WebView page. Calls window.dala._dispatch(json)
in JS, which delivers the data to all window.dala.onMessage handlers.
Reload the current page.
Take a screenshot of the WebView content.
Stop loading the current page.
Functions
@spec eval_js(Phoenix.LiveView.Socket.t(), String.t()) :: Phoenix.LiveView.Socket.t()
Evaluate arbitrary JavaScript in the current WebView and return the result
asynchronously via handle_info({:webview, :eval_result, result}, socket).
The result is JSON-decoded before delivery.
@spec go_forward(Phoenix.LiveView.Socket.t()) :: Phoenix.LiveView.Socket.t()
Go forward in the WebView history (if possible).
@spec interact(Phoenix.LiveView.Socket.t(), tuple()) :: Phoenix.LiveView.Socket.t()
High-level interact API for driving WebView content programmatically.
Actions:
{:tap, selector}- Tap an element matching CSS selector{:type, selector, text}- Type text into an input element{:clear, selector}- Clear an input element{:eval, js_code}- Evaluate JS and return result via:eval_result{:scroll, selector, dx, dy}- Scroll an element by delta{:wait, selector, timeout_ms}- Wait for element to appear (via polling)
Results arrive as handle_info({:webview, :interact_result, %{"action" => ..., "success" => ...}}, socket).
@spec post_message(Phoenix.LiveView.Socket.t(), term()) :: Phoenix.LiveView.Socket.t()
Push a message from Elixir into the WebView page. Calls window.dala._dispatch(json)
in JS, which delivers the data to all window.dala.onMessage handlers.
@spec reload(Phoenix.LiveView.Socket.t()) :: Phoenix.LiveView.Socket.t()
Reload the current page.
@spec screenshot(Phoenix.LiveView.Socket.t()) :: Phoenix.LiveView.Socket.t()
Take a screenshot of the WebView content.
Returns the PNG data as a binary via:
handle_info({:webview, :screenshot, png_data}, socket)Note: Currently not implemented on all platforms.
@spec stop_loading(Phoenix.LiveView.Socket.t()) :: Phoenix.LiveView.Socket.t()
Stop loading the current page.