mirror of
https://github.com/ash-project/ash_phoenix.git
synced 2024-09-20 07:12:49 +12:00
improvement: add add_value/4
and remove_value/3
helpers
This commit is contained in:
parent
a7f2bbafb8
commit
7ed71ba4df
1 changed files with 115 additions and 0 deletions
|
@ -210,6 +210,117 @@ defmodule AshPhoenix do
|
||||||
query.context[:private][:ash_phoenix][:hide_errors] == true
|
query.context[:private][:ash_phoenix][:hide_errors] == true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@add_value_opts [
|
||||||
|
add: [
|
||||||
|
type: :any,
|
||||||
|
doc: "the value to add to the list",
|
||||||
|
default: nil
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
A utility to support "add" buttons on list attributes and arguments used in forms.
|
||||||
|
|
||||||
|
To use, simply pass in the form name of the attribute/argument form as well as the name of the primary/outer form.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# In your template, inside a form called `:change`
|
||||||
|
<button phx-click="append_thing" phx-value-path={{form.path <> "[attribute_name]"}}>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
# In the view/component
|
||||||
|
|
||||||
|
def handle_event("append_thing", %{"path" => path}, socket) do
|
||||||
|
changeset = add_value(socket.assigns.changeset, path, "change")
|
||||||
|
{:noreply, assign(socket, changeset: changeset)}
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options
|
||||||
|
#{Ash.OptionsHelpers.docs(@add_value_opts)}
|
||||||
|
"""
|
||||||
|
@spec add_value(Ash.Changeset.t(), String.t(), String.t(), Keyword.t()) :: Ash.Changeset.t()
|
||||||
|
def add_value(changeset, path, outer_form_name, opts \\ []) do
|
||||||
|
opts = Ash.OptionsHelpers.validate!(opts, @add_value_opts)
|
||||||
|
add = opts[:add]
|
||||||
|
|
||||||
|
[^outer_form_name, key | path] = decode_path(path)
|
||||||
|
|
||||||
|
attribute_or_argument =
|
||||||
|
Ash.Resource.Info.attribute(changeset.resource, key) ||
|
||||||
|
find_argument(changeset, key)
|
||||||
|
|
||||||
|
if attribute_or_argument do
|
||||||
|
value =
|
||||||
|
case attribute_or_argument do
|
||||||
|
%Ash.Resource.Actions.Argument{} = argument ->
|
||||||
|
changeset
|
||||||
|
|> Ash.Changeset.get_argument(argument.name)
|
||||||
|
|> List.wrap()
|
||||||
|
|
||||||
|
attribute ->
|
||||||
|
changeset
|
||||||
|
|> Ash.Changeset.get_attribute(attribute.name)
|
||||||
|
|> List.wrap()
|
||||||
|
end
|
||||||
|
|
||||||
|
new_value = add_to_path(value, path, add)
|
||||||
|
|
||||||
|
case attribute_or_argument do
|
||||||
|
%Ash.Resource.Actions.Argument{} = argument ->
|
||||||
|
Ash.Changeset.set_argument(changeset, argument.name, new_value)
|
||||||
|
|
||||||
|
attribute ->
|
||||||
|
Ash.Changeset.change_attribute(changeset, attribute.name, new_value)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
changeset
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
A utility to support "remove" buttons on list attributes and arguments used in forms.
|
||||||
|
"""
|
||||||
|
@spec remove_value(Ash.Changeset.t(), String.t(), String.t()) :: Ash.Changeset.t()
|
||||||
|
def remove_value(changeset, path, outer_form_name) do
|
||||||
|
[^outer_form_name, key | path] = decode_path(path)
|
||||||
|
|
||||||
|
attribute_or_argument =
|
||||||
|
Ash.Resource.Info.attribute(changeset.resource, key) ||
|
||||||
|
find_argument(changeset, key)
|
||||||
|
|
||||||
|
if attribute_or_argument do
|
||||||
|
value =
|
||||||
|
case attribute_or_argument do
|
||||||
|
%Ash.Resource.Actions.Argument{} = argument ->
|
||||||
|
changeset
|
||||||
|
|> Ash.Changeset.get_argument(argument.name)
|
||||||
|
|> List.wrap()
|
||||||
|
|
||||||
|
attribute ->
|
||||||
|
changeset
|
||||||
|
|> Ash.Changeset.get_attribute(attribute.name)
|
||||||
|
|> List.wrap()
|
||||||
|
end
|
||||||
|
|
||||||
|
new_value = remove_from_path(value, path)
|
||||||
|
|
||||||
|
case attribute_or_argument do
|
||||||
|
%Ash.Resource.Actions.Argument{} = argument ->
|
||||||
|
Ash.Changeset.set_argument(changeset, argument.name, new_value)
|
||||||
|
|
||||||
|
attribute ->
|
||||||
|
Ash.Changeset.change_attribute(changeset, attribute.name, new_value)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
changeset
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp find_argument(changeset, key) do
|
||||||
|
changeset.action && Enum.find(changeset.action.arguments, &(to_string(&1.name) == key))
|
||||||
|
end
|
||||||
|
|
||||||
@add_related_opts [
|
@add_related_opts [
|
||||||
add: [
|
add: [
|
||||||
type: :any,
|
type: :any,
|
||||||
|
@ -657,6 +768,10 @@ defmodule AshPhoenix do
|
||||||
add
|
add
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp add_to_path(value, [], nil) when is_list(value) do
|
||||||
|
value ++ [nil]
|
||||||
|
end
|
||||||
|
|
||||||
defp add_to_path(value, [], add) when is_list(value) do
|
defp add_to_path(value, [], add) when is_list(value) do
|
||||||
value ++ List.wrap(add)
|
value ++ List.wrap(add)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue