Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new_item_builder option to Ecto Adapter #737

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

cervinka
Copy link

@cervinka cervinka commented Jan 2, 2025

This change allows you to change the default form prefill when creating a new entry. This is useful, for example, if we want to create an action to copy an item, or create an item based on a template - these cases are very common in administration.

Example of an action to create a copy of an item:

Add a copy action using item_action:

defmodule MyAppWeb.Backpex.Actions.CopyPreparationCategory do
  use BackpexWeb, :item_action

  @impl Backpex.ItemAction
  def icon(assigns, _item) do
    ~H"""
    <Backpex.HTML.CoreComponents.icon name="hero-document-duplicate" class="h-5 w-5 cursor-pointer transition duration-75 hover:scale-110 hover:text-blue-600" />
    """
  end

  @impl Backpex.ItemAction
  def label(_assigns, _item), do: Backpex.translate("Copy")

  @impl Backpex.ItemAction
  def handle(socket, [item | _items], _data) do
    path =
      Router.get_path(socket, socket.assigns.live_resource, socket.assigns.params, :new, %{
        copy_from: item.id
      })

    {:ok, Phoenix.LiveView.push_patch(socket, to: path)}
  end
end

Add action to LiveResource:

  @impl Backpex.LiveResource
  def item_actions(default_actions) do
    [
      {:copy, %{module: MyAppWeb.Backpex.Actions.CopyPreparationCategory, only: [:row]}}
      | default_actions
    ]
  end

image

Up to now, everything can be done with standard Backpex tools. But we need to create an item with pre-filled values. This is not possible now, but modifying to multiple lines would allow such flexibility.

I suggest to add new optional adapter option new_item_builder , its use would then look like this:

use Backpex.LiveResource,
    adapter_config: [
      ...
      new_item_builder: &__MODULE__.builder/1 # new option
    ],
    ....

  def builder(socket) do
    # we have access to all parameters here
    source_id = socket.assigns.params["copy_from"]

    if source_id do
      source = Preparations.get_preparation_category!(source_id)
      %PreparationCategory{name: source.name, position: source.position}
    else
      %PreparationCategory{}
    end
  end

The implementation is very straightforward. Instead of the existing code for creating new items:

# lib/backpex/live_resource.ex
    empty_item = schema.__struct__()

use this

    new_item = if (builder = live_resource.config(:adapter_config)[:new_item_builder]),
      do: builder.(socket),
      else: schema.__struct__()

I think this small change would increase the possibilities that Backpex offers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant