AshPhoenix (ash_phoenix v0.4.12) View Source

Various helpers and utilities for working with Ash changesets and queries and phoenix.

Link to this section Summary

Functions

A utility to support "add" buttons on embedded types used in forms.

A utility to support "add" buttons on relationships used in forms.

A utility for decoding the path of a form into a list.

Gets all errors on a changeset or query.

A utility to support "remove" buttons on embedded types used in forms.

A utility to support "remove" buttons on relationships used in forms.

Allows for manually transforming errors to modify or enable error messages in the form.

Link to this section Functions

Link to this function

add_embed(query, path, outer_form_name, add \\ %{})

View Source

A utility to support "add" buttons on embedded types used in forms.

To use, simply pass in the form name of the embedded form as well as the name of the primary/outer form.

# In your template, inside a form called `:change`
<button phx-click="append_thing" phx-value-path={{form.path}}>
</button>

# In the view/component

def handle_event("append_thing", %{"path" => path}, socket) do
  changeset = add_embed(socket.assigns.changeset, path, "change")
  {:noreply, assign(socket, changeset: changeset)}
end

You can also pass a specific value to be added, to seed the changes in a customized way. By default, %{} is used.

Link to this function

add_related(changeset, path, outer_form_name, opts \\ [])

View Source

Specs

A utility to support "add" buttons on relationships used in forms.

To use, simply pass in the form name of the relationship form as well as the name of the primary/outer form.

# In your template, inside a form called `:change`
<button phx-click="append_thing" phx-value-path={{form.path}}>
</button>

# In the view/component

def handle_event("append_thing", %{"path" => path}, socket) do
  changeset = add_related(socket.assigns.changeset, path, "change")
  {:noreply, assign(socket, changeset: changeset)}
end

Options

* `:add` - the value to add to the relationship, defaults to `%{}` The default value is `%{}`.
  • :relationship - The relationship being updated, in case it can't be determined from the path

  • :id - The value that should be in meta[:id] in the manage changeset opts. Defaults to the relationship name. This only needs to be set if an id is also provided for inputs_for.

A utility for decoding the path of a form into a list.

For example: change[posts][0][comments][1] ["change", "posts", 0, "comments", 1]

Link to this function

errors_for(changeset_or_query, opts \\ [])

View Source

Specs

errors_for(Ash.Changeset.t() | Ash.Query.t(), Keyword.t()) ::
  [{atom(), {String.t(), Keyword.t()}}] | [String.t()] | map()

Gets all errors on a changeset or query.

This honors the AshPhoenix.FormData.Error protocol and applies any transform_errors. See transform_errors/2 for more information.

Link to this function

hiding_errors?(changeset)

View Source
Link to this function

remove_embed(changeset, path, outer_form_name)

View Source

A utility to support "remove" buttons on embedded types used in forms.

To use, simply pass in the form name of the embedded form as well as the name of the primary/outer form.

# In your template, inside a form called `:change`
<button phx-click="remove_thing" phx-value-path={{form.path}}>
</button>

# In the view/component

def handle_event("remove_thing", %{"path" => path}, socket) do
  changeset = remove_embed(socket.assigns.changeset, path, "change")
  {:noreply, assign(socket, changeset: changeset)}
end
Link to this function

remove_related(changeset, path, outer_form_name, opts \\ [])

View Source

Specs

A utility to support "remove" buttons on relationships used in forms.

To use, simply pass in the form name of the related form as well as the name of the primary/outer form.

# In your template, inside a form called `:change`
<button phx-click="remove_thing" phx-value-path={{form.path}}>
</button>

# In the view/component

def handle_event("remove_thing", %{"path" => path}, socket) do
  {record, changeset} = remove_related(socket.assigns.changeset, path, "change")
  {:noreply, assign(socket, record: record, changeset: changeset)}
end

Options

* `:add` - the value to add to the relationship, defaults to `%{}` The default value is `%{}`.
  • :relationship - The relationship being updated, in case it can't be determined from the path

  • :id - The value that should be in meta[:id] in the manage changeset opts. Defaults to the relationship name. This only needs to be set if an id is also provided for inputs_for.

Link to this function

transform_errors(changeset, transform_errors)

View Source

Specs

transform_errors(
  Ash.Changeset.t() | Ash.Query.t(),
  (Ash.Query.t() | Ash.Changeset.t(), error :: Ash.Error.t() ->
     [{field :: atom(), message :: String.t(), substituations :: Keyword.t()}])
) :: Ash.Query.t() | Ash.Changeset.t()

Allows for manually transforming errors to modify or enable error messages in the form.

By default, only errors that implement the AshPhoenix.FormData.Error protocol will show their errors in forms. This is to protect you from showing strange errors to the user. Using this function, you can intercept those errors (as well as ones that do implement the protocol) and return custom form-ready messages for them.

Example:

AshPhoenix.transform_errors(changeset, fn changeset, %MyApp.CustomError{message: message} ->

{:id, "Something went wrong while doing the %{thing}", [thing: "request"]}

end)

# Could potentially be used for translation, although not quite ergonomic yet defp translate_error(key, msg, vars) do

if vars[:count] do
  Gettext.dngettext(MyApp.Gettext, "errors", msg, msg, count, opts)
else
  Gettext.dgettext(MyApp.Gettext, "errors", msg, opts)
end

end

AshPhoenix.transform_errors(changeset, fn

changeset, %MyApp.CustomError{message: message, field: field} ->
  translate_error(field, message, [foo: :bar])

changeset, any_error ->
  if AshPhoenix.FormData.Error.impl_for(any_error) do
    any_error
    |> AshPhoenix.FormData.error.to_form_error()
    |> List.wrap()
    |> Enum.map(fn {key, msg, vars} ->
      translate_error(key, msg, vars)
    end)
  end

end)