LiveView with Sortable.js, persisting changes to the database

Hi guys,

I’m trying to build a sortable list of items, I’ve been following this tutorial Sortable lists with Phoenix LiveView and SortableJS - Tutorials and screencasts for Elixir, Phoenix and LiveView and it’s good but I have a question regarding persisting changes to the database.

Each item has an id and sort_order number. Sortable.js library takes care of updating the sort_order number. In the handle_event() function, we get ids of all items and their sort_order number is added. Then, for each item get_task() and update_task() functions are run and the order number is persisted in the database.

Now, my code is a little bit different, I get the list of items using Streams and I was wondering if there is a way to avoid using get_task() for each item as all tasks already exist in the stream. I would like to avoid going to the database for each item when it’s already there and available and just update it.

Here’s the code from the tutorial:

def handle_event("update-sorting", %{"ids" => ids}, socket) do
  |> Enum.with_index(1)
  |> Enum.each(fn {"task-" <> id, sort_order}->
    |> Tasks.get_task!()
    |> Tasks.update_task(%{sort_order: sort_order})

  {:noreply, socket}

You could use one update_all per record.

require Ecto.Query

|> Enum.with_index(1)
|> Enum.each(fn {"task-" <> id, sort_order}->
  query =
    from Task,
      where: [id: id],
      update: [set: [sort_order: ^sort_order]]

  MyApp.Repo.update_all(query, [])

You can of course move the appropriate stuff to your context.