1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

wslでelixir その159

Last updated at Posted at 2025-03-12

概要

wsl(wsl2じゃない)で、elixirやってみた。
Livebookの、kino.jsを調査してみた。

setup

Mix.install([
  {:kino, "~> 0.15.0"}
])

サンプルコード

defmodule KinoGuide.HTML do
  use Kino.JS
  def new(html) when is_binary(html) do
    Kino.JS.new(__MODULE__, html)
  end
  asset "main.js" do
    """
    export function init(ctx, html) {
      ctx.root.innerHTML = html;
    }
    """
  end
end

KinoGuide.HTML.new("""
<h3>Look!</h3>

<p>I wrote this HTML from <strong>Kino</strong>!</p>
""")

defmodule KinoGuide.Counter do
  use Kino.JS
  use Kino.JS.Live
  def new(count) do
    Kino.JS.Live.new(__MODULE__, count)
  end
  def bump(kino) do
    Kino.JS.Live.cast(kino, :bump)
  end
  @impl true
  def init(count, ctx) do
    {:ok, assign(ctx, count: count)}
  end
  @impl true
  def handle_connect(ctx) do
    {:ok, ctx.assigns.count, ctx}
  end
  @impl true
  def handle_cast(:bump, ctx) do
    {:noreply, bump_count(ctx)}
  end
  @impl true
  def handle_event("bump", _, ctx) do
    IO.puts("ok")
    {:noreply, bump_count(ctx)}
  end
  defp bump_count(ctx) do
    ctx = update(ctx, :count, &(&1 + 1))
    broadcast_event(ctx, "update", ctx.assigns.count)
    ctx
  end
  asset "main.js" do
    """
    export function init(ctx, count) {
      ctx.root.innerHTML = `
        <div id="count"></div>
        <button id="bump">Bump</button>
      `;
      const countEl = document.getElementById("count");
      const bumpEl = document.getElementById("bump");
      countEl.innerHTML = count;
      ctx.handleEvent("update", (count) => {
        countEl.innerHTML = count;
      });
      bumpEl.addEventListener("click", (event) => {
        ctx.pushEvent("bump");
      });
    }
    """
  end
end

counter = KinoGuide.Counter.new(0)

KinoGuide.Counter.bump(counter)

defmodule KinoDocs.LiveHTML do
	use Kino.JS
	use Kino.JS.Live
	def new(html) do
		Kino.JS.Live.new(__MODULE__, html)
	end
	def replace(kino, html) do
		Kino.JS.Live.cast(kino, {:replace, html})
	end
	@impl true
	def init(html, ctx) do
		{:ok, assign(ctx, html: html)}
	end
	@impl true
	def handle_connect(ctx) do
		{:ok, ctx.assigns.html, ctx}
	end
	@impl true
	def handle_cast({:replace, html}, ctx) do
		broadcast_event(ctx, "replace", html)
		{:noreply, assign(ctx, html: html)}
	end
	asset "main.js" do
		"""
		export function init(ctx, html) {
			ctx.root.innerHTML = html;
			ctx.handleEvent("replace", (html) => {
				ctx.root.innerHTML = html;
			});
		}
		"""
	end
end

list = KinoDocs.LiveHTML.new("""
<h1>Hello</h1>
""")

KinoDocs.LiveHTML.replace(list, """
<h2 style="color: red">World</h2>
""")

defmodule KinoCustom.Bar do
  use Kino.JS
  use Kino.JS.Live

  def new(width) do
    Kino.JS.Live.new(__MODULE__, width)
  end

  def update(kino, width) do
    Kino.JS.Live.cast(kino, {:update, width})
  end

  @impl true
  def init(html, ctx) do
    {:ok, assign(ctx, html: html)}
  end

  @impl true
  def handle_connect(ctx) do
    {:ok, ctx.assigns.html, ctx}
  end

  @impl true
  def handle_cast({:update, width}, ctx) do
    broadcast_event(ctx, "update", width)
    {:noreply, assign(ctx, width: width)}
  end

  asset "main.js" do
    """
    export function init(ctx, width) {
      const bar = document.createElement("div");
      bar.className = "bar";
      bar.style.width = width;
      bar.style.height = "40px";
      bar.style.backgroundColor = "aqua";
      ctx.root.appendChild(bar);
      ctx.handleEvent("update", (width) => {
        bar.style.width = width
      });
    }
    """
  end
end

bar = KinoCustom.Bar.new("50%")

Stream.interval(250)
|> Stream.take(100)
|> Kino.animate(fn width ->
  KinoCustom.Bar.update(bar, "#{width}%")
end)


elixirからjs呼び出し

KinoCustom.Bar.update(bar, "#{width}%")

jsからelixir呼び出し

ctx.pushEvent("bump");

以上。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?