Retrieving values from assigns map in LIveview Surface

Hi, I’m trying to leverage liveview surface to render a list of points eventually converting that list to coordinates to create tetro shapes for a tetris game. I can view the list of points on the live_view page by inspecting the shape and calling a function retrieving the points.

  def render(assigns) do
    ~F"""
    <Title message={@title} id="title" />
    <pre>
  { inspect Shape.from_tetro(@tetro) }
    </pre>
    """
  end

  @impl true
  def mount(_params, _session, socket) do
    {:ok, assign(socket, tetro: Tetro.new(:j), title: "Welcome to FreeFall!")}
  end

The issue we’re seeing is when we’re trying to obtain that list from within a surface component. That will be used above. Elixir complains about @points and we’re explicitly setting it in the mount callback. Am I overlooking something?

defmodule FreeFallWeb.Live.Components.Shape do
  use Surface.LiveComponent
  alias FreeFall.Game.Shape

  prop(tetro, :map, required: true)

  def mount(socket, %{position: position} = tetro) do
    {:ok, assign(socket, position: position, points: Shape.from_tetro(tetro))}
  end

  def render(assigns) do
    ~F"""
    {#for point <- @points}
      {inspect point}
    {/for}
    """
  end
end

data points, :list
data position, :any

Surface wants you to specify all assigns.

https://surface-ui.org/data

Unrelated, but does it need to be Live component? Does the shape handle events?

Eventually I’ll wire in event handling to the shape, to move it left, right, rotate.

Depending on how complicated your live view is, how many shapes you have on the page, etc, it might be more performant to handle them in the view. There is a slight cost to live components vs function components.

Have fun :grin:

mount/1 callback takes only the socket. Perhaps you’ve meant to use update/2?

1 Like

Thanks for your help, greatly appreciated. we’ve simplified the component and were able to retrieve the points through setting the properties at the liveview level to the Shape component which we got working by adding the declaration for points in the Shape component. Using a comprehension we’ll be emitting a Point component per point tuple.