LiveView es una librería Elixir/Phoenix. Nos permite implementar aplicaciones interactivas sin usar javascript más allá de lo mínimo. En esta publicación, intentaré ilustrar cómo funciona, mostrando un caso de uso donde lo apliqué con éxito.
Propongo el siguiente escenario (caso común): necesitamos filtrar los datos de una base de datos y el tamaño de los datos es lo suficientemente grande como para evitar que se filtre directamente en javascript.
Hay 2 enfoques que vienen rápidamente a la mente (que supongo que el lector está familiarizado):
El primer enfoque requiere una recarga de la página y no será interactivo en absoluto. El segundo enfoque no necesita recargar la página y se puede hacer que sea altamente interactivo, pero se agrega complejidad adicional ya que se necesita crear y mantener una aplicación separada para esta tarea aparentemente simple.
LiveView proporciona una tercera forma: escribir solo el código del lado del servidor, al tiempo que proporciona interactividad en tiempo real y evita la recarga de páginas. Puede encontrar información detallada en https://dockyard.com/blog/2018/12/12/phoenix-liveview-interactive-real-time-apps-no-need-to-write-javascript
El enfoque es básicamente el siguiente:
Una vez que se establece la conexión, hay algunos eventos en el cliente que se propagan al servidor, el servidor actualiza el estado y luego se envía una diferencia mínima de DOM (diferencias de DOM con respecto a la versión anterior) al cliente para que se procese.
Me enfocaré en implementar el escenario propuesto. Para obtener instrucciones de instalación, lea la documentación. Además, utilizaremos una función llamada retrieve_items que opcionalmente recibe un mapa con los filtros para aplicar. Esta función no se implementará en el siguiente ejercicio, solo asumiremos que recupera correctamente la información de la base de datos y la filtra como se esperaba.
Hay 4 cosas que deben hacerse para implementar nuestro LiveView:
Revisaré cada punto de esta lista en detalle.
Los LiveViews se pueden adjuntar a rutas, controladores o plantillas. Esta vez iremos con plantillas:
def index(conn, _params) do live_render(conn, MyApp.MyLiveView) end
La función mount es donde inicializamos el LiveView. Básicamente establecemos qué es un «estado conocido estable». En nuestro caso, simplemente podemos agregar un filtro en blanco (datos sin filtrar):
def mount(_params, socket) do my_items = retrieve_items() {:ok, assign(socket, %{ items: my_items, filter_state: %{ "param_a" => "", "param_b" => "" } })} end
Agregue los eventos a la plantilla para que podamos reaccionar a los cambios:
<%= form_for :my_filter, "#", [phx_change: :filter, phx_submit: :ignore], fn f -> %> <%= label f, :param_a, "Filter by param_a" %> <%= text_input f, :param_a, class: "form-control", "Search by param_a", value: @filter_state["param_a"] %> <%= label f, :param_b, "Filter by param_b" %> <%= text_input f, :param_b, class: "form-control", "Search by param_b", value: @filter_state["param_b"] %> <% end %> <%= for item <- @items do %> <%= item.name %> <% end %>
Agregue las funciones para reaccionar a los eventos del cliente:
def handle_event( "filter", %{"_target" => ["my_filter", param], "my_filter" => my_filter}, socket ) do %{^param => value} = my_filter filter = Map.put(socket.assigns.filter_state, param, value) my_items = retrieve_items(filter) {:noreply, assign(socket, items: my_items, filter_state: filter )} end
Y ya hemos terminado. El formulario tiene phx_change: filter
cuando se declara. Estos valores le dicen a LiveView que llame al método handle_event con el parámetro filter
. Podría tener varios de esos parámetros y reaccionar según sea necesario en esos casos.
LiveView es un enfoque que está ganando terreno. Hay otras bibliotecas que intentan hacer algo similar en otros marcos (como, por ejemplo, Reactor para Django). Encontré que LiveView es muy fácil de trabajar, y la sensación que se tiene cuando se está del lado del usuario es que es rápido. Obviamente, este es un ejemplo muy simple, y se pueden implementar cosas más sofisticadas, así que pruébelo.
Hay un par de desafíos que enfrentar cuando se trabaja con este enfoque:
Hasta ahora, estoy satisfecho con lo que he podido lograr y tengo la intención de seguir usándolo en el futuro.