Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Phoenix LiveView チュートリアル

Phoenix LiveView チュートリアル

Phoenix LiveView チュートリアル
https://github.com/ne-sachirou/phoenix_live_view_sample

4b071f90c5d9c0a58e2d9076460b7be4?s=128

さっちゃん

June 14, 2019
Tweet

Transcript

  1. Phoenix LiveView チュート Phoenix LiveView チュート リアル リアル

  2. 2019-06 の theme は、 2019-06 の theme は、 Phoenix LiveView

    Phoenix LiveView
  3. Phoenix |> とは Phoenix |> とは Elixir の Web Application

    Framework (Ruby on Rails っぽいもの) で Elixir の Web Application Framework (Ruby on Rails っぽいもの) で す。Rails と同じく、RDB と連携した Web Application を素早く簡單に す。Rails と同じく、RDB と連携した Web Application を素早く簡單に 作れます。 作れます。 https://phoenixframework.org/ https://phoenixframework.org/
  4. 加えて、 加えて、 Phoenix.Channel Phoenix.Channelと云ふ仕組みで、WebSocket を通した multi と云ふ仕組みで、WebSocket を通した multi user

    & real-time application (典型的には chat) を素早く簡單に作れま user & real-time application (典型的には chat) を素早く簡單に作れま す。 す。
  5. Phoenix LiveView |> とは Phoenix LiveView |> とは 「わっちは Web

    browser の表⽰を real-time に更新したいだけなんぢ 「わっちは Web browser の表⽰を real-time に更新したいだけなんぢ ゃ! それだけの爲に JavaScript なんぞを書きとうない! (異論は認める)」 ゃ! それだけの爲に JavaScript なんぞを書きとうない! (異論は認める)」
  6. sever-side の Elixir で HTML を吐く code を書くだけで、real-time に sever-side

    の Elixir で HTML を吐く code を書くだけで、real-time に Web browser の表⽰を更新できる!? Web browser の表⽰を更新できる!? https://github.com/phoenixframework/phoenix_live_view https://github.com/phoenixframework/phoenix_live_view
  7. Do It. Do It.

  8. Erlang と Elixir が⼊ってゐる事を確か Erlang と Elixir が⼊ってゐる事を確か める める

    elixir -v elixir -v ⼊ってゐなければ (asdf, anyenv 等は御好みに)、 ⼊ってゐなければ (asdf, anyenv 等は御好みに)、 brew install erlang elixir brew install erlang elixir Ubuntu (WSL 含む) は Ubuntu (WSL 含む) は https://www.erlang- https://www.erlang- solutions.com/resources/download.html solutions.com/resources/download.html から。 から。
  9. Node.js を⼊れる Node.js を⼊れる brew install node brew install node

    node -v node -v Ubuntu (WSL を含む) は Ubuntu (WSL を含む) は https://github.com/nodesource/distributions/blob/master/README. https://github.com/nodesource/distributions/blob/master/README. md md から。 から。
  10. MySQL (MariaDB) を⼊れる MySQL (MariaDB) を⼊れる brew install mysql brew

    install mysql brew services start mysql brew services start mysql
  11. Phoenix を⼊れる Phoenix を⼊れる https://hexdocs.pm/phoenix/installation.html https://hexdocs.pm/phoenix/installation.html mix archive.install hex phx_new

    mix archive.install hex phx_new
  12. Web application を作る Web application を作る https://hexdocs.pm/phoenix/up_and_running.html https://hexdocs.pm/phoenix/up_and_running.html mix mix

    help help phx.new phx.new mix phx.new hello --umbrella --database mysql mix phx.new hello --umbrella --database mysql cd cd hello_umbrella hello_umbrella ( (cd cd apps/hello_web/assets && npm install) apps/hello_web/assets && npm install) mix ecto.create mix ecto.create iex -S mix phx.server iex -S mix phx.server http://localhost:4000/ http://localhost:4000/
  13. Phoenix LiveView を⼊れる Phoenix LiveView を⼊れる ^C ^C で phx.server

    を落とす。 ( で phx.server を落とす。 ( mix.exs mix.exs や や config/ config/ を書き換へた時に を書き換へた時に は LiveReload が效かないので、再起動する。) は LiveReload が效かないので、再起動する。) diff --git a/apps/hello_web/mix.exs b/apps/hello_web/mix.exs diff --git a/apps/hello_web/mix.exs b/apps/hello_web/mix.exs index b5158fc..33aa0de 100644 index b5158fc..33aa0de 100644 --- a/apps/hello_web/mix.exs --- a/apps/hello_web/mix.exs +++ b/apps/hello_web/mix.exs +++ b/apps/hello_web/mix.exs @@ -42,6 +42,7 @@ defmodule HelloWeb.MixProject do @@ -42,6 +42,7 @@ defmodule HelloWeb.MixProject do {:phoenix_ecto, "~> 4.0"}, {:phoenix_ecto, "~> 4.0"}, {:phoenix_html, "~> 2.11"}, {:phoenix_html, "~> 2.11"}, {:phoenix_live_reload, "~> 1.2", only: :dev}, {:phoenix_live_reload, "~> 1.2", only: :dev}, + {:phoenix_live_view, github: "phoenixframework/phoenix_live_view"}, + {:phoenix_live_view, github: "phoenixframework/phoenix_live_view"}, {:gettext, "~> 0.11"}, {:gettext, "~> 0.11"}, {:hello, in_umbrella: true}, {:hello, in_umbrella: true}, {:jason, "~> 1.0"}, {:jason, "~> 1.0"}, mix deps.get mix deps.get
  14. mix phx.gen.secret 32 mix phx.gen.secret 32 # SECRET_SALT # SECRET_SALT

    diff --git a/config/config.exs b/config/config.exs diff --git a/config/config.exs b/config/config.exs index d5b58e4..c40d159 100644 index d5b58e4..c40d159 100644 --- a/config/config.exs --- a/config/config.exs +++ b/config/config.exs +++ b/config/config.exs @@ -22,7 +22,8 @@ config :hello_web, HelloWeb.Endpoint, @@ -22,7 +22,8 @@ config :hello_web, HelloWeb.Endpoint, url: [host: "localhost"], url: [host: "localhost"], secret_key_base: "JQ/tn4vM/UDSW/BkHsotJKRpvugZMOGuL51u/j8LzYjIh+elejWrL7jgEt8vZIdt", secret_key_base: "JQ/tn4vM/UDSW/BkHsotJKRpvugZMOGuL51u/j8LzYjIh+elejWrL7jgEt8vZIdt", render_errors: [view: HelloWeb.ErrorView, accepts: ~w(html json)], render_errors: [view: HelloWeb.ErrorView, accepts: ~w(html json)], - pubsub: [name: HelloWeb.PubSub, adapter: Phoenix.PubSub.PG2] - pubsub: [name: HelloWeb.PubSub, adapter: Phoenix.PubSub.PG2] + pubsub: [name: HelloWeb.PubSub, adapter: Phoenix.PubSub.PG2], + pubsub: [name: HelloWeb.PubSub, adapter: Phoenix.PubSub.PG2], + live_view: [signing_salt: "SECRET_SALT"] + live_view: [signing_salt: "SECRET_SALT"] # Configures Elixir's Logger # Configures Elixir's Logger config :logger, :console, config :logger, :console,
  15. diff --git a/apps/hello_web/lib/hello_web/router.ex b/apps/hello_web/lib/hello_web/router.ex diff --git a/apps/hello_web/lib/hello_web/router.ex b/apps/hello_web/lib/hello_web/router.ex index e691cdb..3983991

    100644 index e691cdb..3983991 100644 --- a/apps/hello_web/lib/hello_web/router.ex --- a/apps/hello_web/lib/hello_web/router.ex +++ b/apps/hello_web/lib/hello_web/router.ex +++ b/apps/hello_web/lib/hello_web/router.ex @@ -7,6 +7,8 @@ defmodule HelloWeb.Router do @@ -7,6 +7,8 @@ defmodule HelloWeb.Router do plug :fetch_flash plug :fetch_flash plug :protect_from_forgery plug :protect_from_forgery plug :put_secure_browser_headers plug :put_secure_browser_headers + plug :fetch_flash + plug :fetch_flash + plug Phoenix.LiveView.Flash + plug Phoenix.LiveView.Flash end end pipeline :api do pipeline :api do
  16. diff --git a/apps/hello_web/lib/hello_web.ex b/apps/hello_web/lib/hello_web.ex diff --git a/apps/hello_web/lib/hello_web.ex b/apps/hello_web/lib/hello_web.ex index 9cf6215..9055872

    100644 index 9cf6215..9055872 100644 --- a/apps/hello_web/lib/hello_web.ex --- a/apps/hello_web/lib/hello_web.ex +++ b/apps/hello_web/lib/hello_web.ex +++ b/apps/hello_web/lib/hello_web.ex @@ -22,6 +22,7 @@ defmodule HelloWeb do @@ -22,6 +22,7 @@ defmodule HelloWeb do use Phoenix.Controller, namespace: HelloWeb use Phoenix.Controller, namespace: HelloWeb import Plug.Conn import Plug.Conn import HelloWeb.Gettext import HelloWeb.Gettext + import Phoenix.LiveView.Controller, only: [live_render: 3] + import Phoenix.LiveView.Controller, only: [live_render: 3] alias HelloWeb.Router.Helpers, as: Routes alias HelloWeb.Router.Helpers, as: Routes end end end end @@ -40,6 +41,7 @@ defmodule HelloWeb do @@ -40,6 +41,7 @@ defmodule HelloWeb do import HelloWeb.ErrorHelpers import HelloWeb.ErrorHelpers import HelloWeb.Gettext import HelloWeb.Gettext + import Phoenix.LiveView, only: [live_render: 2, live_render: 3] + import Phoenix.LiveView, only: [live_render: 2, live_render: 3] alias HelloWeb.Router.Helpers, as: Routes alias HelloWeb.Router.Helpers, as: Routes end end end end @@ -49,6 +51,7 @@ defmodule HelloWeb do @@ -49,6 +51,7 @@ defmodule HelloWeb do use Phoenix.Router use Phoenix.Router import Plug.Conn import Plug.Conn import Phoenix.Controller import Phoenix.Controller + import Phoenix.LiveView.Router + import Phoenix.LiveView.Router end end end end
  17. diff --git a/apps/hello_web/lib/hello_web/endpoint.ex b/apps/hello_web/lib/hello_web/endpoint.ex diff --git a/apps/hello_web/lib/hello_web/endpoint.ex b/apps/hello_web/lib/hello_web/endpoint.ex index 3e89975..c03dbb9

    100644 index 3e89975..c03dbb9 100644 --- a/apps/hello_web/lib/hello_web/endpoint.ex --- a/apps/hello_web/lib/hello_web/endpoint.ex +++ b/apps/hello_web/lib/hello_web/endpoint.ex +++ b/apps/hello_web/lib/hello_web/endpoint.ex @@ -5,6 +5,8 @@ defmodule HelloWeb.Endpoint do @@ -5,6 +5,8 @@ defmodule HelloWeb.Endpoint do websocket: true, websocket: true, longpoll: false longpoll: false + socket "/live", Phoenix.LiveView.Socket + socket "/live", Phoenix.LiveView.Socket + + # Serve at "/" the static files from "priv/static" directory. # Serve at "/" the static files from "priv/static" directory. # # # You should set gzip to true if you are running phx.digest # You should set gzip to true if you are running phx.digest
  18. diff --git a/apps/hello_web/assets/package.json b/apps/hello_web/assets/package.json diff --git a/apps/hello_web/assets/package.json b/apps/hello_web/assets/package.json index eaf01c6..5c5a8d0

    100644 index eaf01c6..5c5a8d0 100644 --- a/apps/hello_web/assets/package.json --- a/apps/hello_web/assets/package.json +++ b/apps/hello_web/assets/package.json +++ b/apps/hello_web/assets/package.json @@ -7,7 +7,8 @@ @@ -7,7 +7,8 @@ }, }, "dependencies": { "dependencies": { "phoenix": "file:../../../deps/phoenix", "phoenix": "file:../../../deps/phoenix", - "phoenix_html": "file:../../../deps/phoenix_html" - "phoenix_html": "file:../../../deps/phoenix_html" + "phoenix_html": "file:../../../deps/phoenix_html", + "phoenix_html": "file:../../../deps/phoenix_html", + "phoenix_live_view": "file:../../../deps/phoenix_live_view" + "phoenix_live_view": "file:../../../deps/phoenix_live_view" }, }, "devDependencies": { "devDependencies": { "@babel/core": "^7.0.0", "@babel/core": "^7.0.0", ( (cd cd apps/hello_web/assets && npm install) apps/hello_web/assets && npm install)
  19. diff --git a/apps/hello_web/assets/css/app.css b/apps/hello_web/assets/css/app.css diff --git a/apps/hello_web/assets/css/app.css b/apps/hello_web/assets/css/app.css index fec0b3f..416abc2

    100644 index fec0b3f..416abc2 100644 --- a/apps/hello_web/assets/css/app.css --- a/apps/hello_web/assets/css/app.css +++ b/apps/hello_web/assets/css/app.css +++ b/apps/hello_web/assets/css/app.css @@ -1,3 +1,4 @@ @@ -1,3 +1,4 @@ /* This file is for your main application css. */ /* This file is for your main application css. */ @import "./phoenix.css"; @import "./phoenix.css"; +@import "../../../../deps/phoenix_live_view/assets/css/live_view.css"; +@import "../../../../deps/phoenix_live_view/assets/css/live_view.css"; \ No newline at end of file \ No newline at end of file diff --git a/apps/hello_web/assets/js/app.js b/apps/hello_web/assets/js/app.js diff --git a/apps/hello_web/assets/js/app.js b/apps/hello_web/assets/js/app.js index 8a5d386..719c0ab 100644 index 8a5d386..719c0ab 100644 --- a/apps/hello_web/assets/js/app.js --- a/apps/hello_web/assets/js/app.js +++ b/apps/hello_web/assets/js/app.js +++ b/apps/hello_web/assets/js/app.js @@ -15,3 +15,8 @@ import "phoenix_html" @@ -15,3 +15,8 @@ import "phoenix_html" // // // Local files can be imported directly using relative paths, for example: // Local files can be imported directly using relative paths, for example: // import socket from "./socket" // import socket from "./socket" + + +import LiveSocket from "phoenix_live_view" +import LiveSocket from "phoenix_live_view" + + +let liveSocket = new LiveSocket("/live") +let liveSocket = new LiveSocket("/live") +liveSocket.connect() +liveSocket.connect()
  20. diff --git a/config/dev.exs b/config/dev.exs diff --git a/config/dev.exs b/config/dev.exs index d286f50..121eb30

    100644 index d286f50..121eb30 100644 --- a/config/dev.exs --- a/config/dev.exs +++ b/config/dev.exs +++ b/config/dev.exs @@ -61,7 +61,8 @@ config :hello_web, HelloWeb.Endpoint, @@ -61,7 +61,8 @@ config :hello_web, HelloWeb.Endpoint, ~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$", ~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$", ~r"priv/gettext/.*(po)$", ~r"priv/gettext/.*(po)$", ~r"lib/hello_web/{live,views}/.*(ex)$", ~r"lib/hello_web/{live,views}/.*(ex)$", - ~r"lib/hello_web/templates/.*(eex)$" - ~r"lib/hello_web/templates/.*(eex)$" + ~r"lib/hello_web/templates/.*(eex)$", + ~r"lib/hello_web/templates/.*(eex)$", + ~r{lib/hello_web/live/.*(ex)$} + ~r{lib/hello_web/live/.*(ex)$} ] ] ] ]
  21. Phoenix でページを作ってみる Phoenix でページを作ってみる cd cd apps/hello_web apps/hello_web mix phx.gen.html

    Accounts Users users name:string mix phx.gen.html Accounts Users users name:string mix ecto.migrate mix ecto.migrate diff --git a/apps/hello_web/lib/hello_web/router.ex b/apps/hello_web/lib/hello_web/router.ex diff --git a/apps/hello_web/lib/hello_web/router.ex b/apps/hello_web/lib/hello_web/router.ex index 3983991..2f96646 100644 index 3983991..2f96646 100644 --- a/apps/hello_web/lib/hello_web/router.ex --- a/apps/hello_web/lib/hello_web/router.ex +++ b/apps/hello_web/lib/hello_web/router.ex +++ b/apps/hello_web/lib/hello_web/router.ex @@ -19,6 +19,7 @@ defmodule HelloWeb.Router do @@ -19,6 +19,7 @@ defmodule HelloWeb.Router do pipe_through :browser pipe_through :browser get "/", PageController, :index get "/", PageController, :index + resources "/users", UsersController + resources "/users", UsersController end end # Other scopes may use custom stacks # Other scopes may use custom stacks http://localhost:4000/users http://localhost:4000/users
  22. LiveView を埋め込む! LiveView を埋め込む! diff --git a/apps/hello_web/lib/hello_live.ex b/apps/hello_web/lib/hello_live.ex diff --git

    a/apps/hello_web/lib/hello_live.ex b/apps/hello_web/lib/hello_live.ex new file mode 100644 new file mode 100644 index 0000000..d362431 index 0000000..d362431 --- /dev/null --- /dev/null +++ b/apps/hello_web/lib/hello_live.ex +++ b/apps/hello_web/lib/hello_live.ex @@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@ +defmodule HelloWeb.HelloLive do +defmodule HelloWeb.HelloLive do + use Phoenix.LiveView + use Phoenix.LiveView + + + def render(assigns) do + def render(assigns) do + ~L""" + ~L""" + Count: <%= @count %> + Count: <%= @count %> + """ + """ + end + end + + + def mount(%{}, socket) do + def mount(%{}, socket) do + if connected?(socket), do: :timer.send_interval(1000, self(), :update) + if connected?(socket), do: :timer.send_interval(1000, self(), :update) + {:ok, assign(socket, :count, 0)} + {:ok, assign(socket, :count, 0)} + end + end + + + def handle_info(:update, socket) do + def handle_info(:update, socket) do + count = socket.assigns.count + count = socket.assigns.count + {:noreply, assign(socket, :count, count + 1)} + {:noreply, assign(socket, :count, count + 1)} + end + end +end +end
  23. diff --git a/apps/hello_web/lib/hello_web/templates/users/index.html.eex b/apps/hello_web/lib/hello_web/templates/users/index.html.eex diff --git a/apps/hello_web/lib/hello_web/templates/users/index.html.eex b/apps/hello_web/lib/hello_web/templates/users/index.html.eex index 45d0dd8..ebbce2b

    100644 index 45d0dd8..ebbce2b 100644 --- a/apps/hello_web/lib/hello_web/templates/users/index.html.eex --- a/apps/hello_web/lib/hello_web/templates/users/index.html.eex +++ b/apps/hello_web/lib/hello_web/templates/users/index.html.eex +++ b/apps/hello_web/lib/hello_web/templates/users/index.html.eex @@ -1,5 +1,7 @@ @@ -1,5 +1,7 @@ <h1>Listing Users</h1> <h1>Listing Users</h1> +<p><%= Phoenix.LiveView.live_render(@conn, HelloWeb.HelloLive, session: %{}) %></p> +<p><%= Phoenix.LiveView.live_render(@conn, HelloWeb.HelloLive, session: %{}) %></p> + + <table> <table> <thead> <thead> <tr> <tr>
  24. 上り! 上り! diff --git a/apps/hello_web/lib/hello_live.ex b/apps/hello_web/lib/hello_live.ex diff --git a/apps/hello_web/lib/hello_live.ex b/apps/hello_web/lib/hello_live.ex

    index d362431..8cf71aa 100644 index d362431..8cf71aa 100644 --- a/apps/hello_web/lib/hello_live.ex --- a/apps/hello_web/lib/hello_live.ex +++ b/apps/hello_web/lib/hello_live.ex +++ b/apps/hello_web/lib/hello_live.ex @@ -4,16 +4,27 @@ defmodule HelloWeb.HelloLive do @@ -4,16 +4,27 @@ defmodule HelloWeb.HelloLive do def render(assigns) do def render(assigns) do ~L""" ~L""" Count: <%= @count %> Count: <%= @count %> + <button phx-click="reverse">リバ!</button> + <button phx-click="reverse">リバ!</button> """ """ end end def mount(%{}, socket) do def mount(%{}, socket) do if connected?(socket), do: :timer.send_interval(1000, self(), :update) if connected?(socket), do: :timer.send_interval(1000, self(), :update) - {:ok, assign(socket, :count, 0)} - {:ok, assign(socket, :count, 0)} + socket = + socket = + socket + socket + |> assign(:count, 0) + |> assign(:count, 0) + |> assign(:diff, 1) + |> assign(:diff, 1) + {:ok, socket} + {:ok, socket} + end + end + + + def handle_event("reverse", _value, socket) do + def handle_event("reverse", _value, socket) do + diff = socket.assigns.diff + diff = socket.assigns.diff + {:noreply, assign(socket, :diff, -diff)} + {:noreply, assign(socket, :diff, -diff)} end end def handle_info(:update, socket) do def handle_info(:update, socket) do count = socket.assigns.count count = socket.assigns.count - {:noreply, assign(socket, :count, count + 1)} - {:noreply, assign(socket, :count, count + 1)} + diff = socket.assigns.diff + diff = socket.assigns.diff + {:noreply, assign(socket, :count, count + diff)} + {:noreply, assign(socket, :count, count + diff)} end end end end \ No newline at end of file \ No newline at end of file
  25. Playing time. Playing time.