Refresh "calculations" during form.validate

This question is kind of similar to https://discordapp.com/channels/711271361523351632/1071883200378445854/1071883200378445854 However, that example is a simple calculation involving two of the readily available form fields, whereas mine isn't as simple in that one of the inputs needs an aggregation of counts from an embedded array field as shown below. I want to be able to display the remaining count of an item which would decrease as the user increases the usage count.
calculate :item_remaining_count,
:integer,
MyApp.Calculations.ActionCountsHelpers
calculate :item_remaining_count,
:integer,
MyApp.Calculations.ActionCountsHelpers
defmodule MyApp.Calculations.ActionCountsHelpers do
use Ash.Calculation

@impl true
def calculate(records, opts, params) do
Enum.map(records, fn record ->
ActionCountHelpers.item_remaining_count(records) ## << Error happens here.
end)
end
end

def sum_usage_count(%Item{} = item) do
if item.usage_embeds do
Enum.reduce(item.usage_embeds , 0, fn cnt, acc -> acc + cnt.usage_count end)

else
0
end
end

def item_remaining_count(%Item{} = item) do
item.item_count - sum_usage_count(item)
end
defmodule MyApp.Calculations.ActionCountsHelpers do
use Ash.Calculation

@impl true
def calculate(records, opts, params) do
Enum.map(records, fn record ->
ActionCountHelpers.item_remaining_count(records) ## << Error happens here.
end)
end
end

def sum_usage_count(%Item{} = item) do
if item.usage_embeds do
Enum.reduce(item.usage_embeds , 0, fn cnt, acc -> acc + cnt.usage_count end)

else
0
end
end

def item_remaining_count(%Item{} = item) do
item.item_count - sum_usage_count(item)
end
I'm not sure how to initiate the re-calculation, but here is what I tried.
def handle_event("validate", %{"form" => form_params} = params, socket) do

form = AshPhoenix.Form.validate(socket.assigns.form, form_params)
MyApp.Projects.Item.item_remaining_count() # <<<

{:noreply, assign(socket, form: form)}
end
def handle_event("validate", %{"form" => form_params} = params, socket) do

form = AshPhoenix.Form.validate(socket.assigns.form, form_params)
MyApp.Projects.Item.item_remaining_count() # <<<

{:noreply, assign(socket, form: form)}
end
3 Replies
Jason
JasonOP3y ago
Then I get an error message
** (ArithmeticError) bad argument in arithmetic expression
:erlang.-(nil, 0)
(myapp 0.1.0) lib/myapp/projects/calculations/action_counts_helpers.ex:##
: MyApp.Calculations.ActionCountHelpers.item_remaining_count/1
(elixir 1.14.1) lib/enum.ex:1658: Enum."-map/2-lists^map/1-0-"/2
(ash 2.6.10) lib/ash/api/api.ex:460: Ash.Api.calculate/3
(myapp 0.1.0) lib/myapp/projects/projects.ex:1: myapp.projects.calculate/3
(myapp 0.1.0) lib/myapp_web/live/usage_live/action_live.ex:227: myappWeb.UsageLive.actionLive.handle_event/3
(phoenix_live_view 0.18.15) lib/phoenix_live_view/channel.ex:396: anonymous fn/3 in Phoenix.LiveView.Channel.view_handle_event/3
(telemetry 1.2.1) c:/Users/gobey/_dev/myapp_ash/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
(phoenix_live_view 0.18.15) lib/phoenix_live_view/channel.ex:216: Phoenix.LiveView.Channel.handle_info/2
(stdlib 4.0.1) gen_server.erl:1120: :gen_server.try_dispatch/4
(stdlib 4.0.1) gen_server.erl:1197: :gen_server.handle_msg/6
(stdlib 4.0.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
** (ArithmeticError) bad argument in arithmetic expression
:erlang.-(nil, 0)
(myapp 0.1.0) lib/myapp/projects/calculations/action_counts_helpers.ex:##
: MyApp.Calculations.ActionCountHelpers.item_remaining_count/1
(elixir 1.14.1) lib/enum.ex:1658: Enum."-map/2-lists^map/1-0-"/2
(ash 2.6.10) lib/ash/api/api.ex:460: Ash.Api.calculate/3
(myapp 0.1.0) lib/myapp/projects/projects.ex:1: myapp.projects.calculate/3
(myapp 0.1.0) lib/myapp_web/live/usage_live/action_live.ex:227: myappWeb.UsageLive.actionLive.handle_event/3
(phoenix_live_view 0.18.15) lib/phoenix_live_view/channel.ex:396: anonymous fn/3 in Phoenix.LiveView.Channel.view_handle_event/3
(telemetry 1.2.1) c:/Users/gobey/_dev/myapp_ash/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
(phoenix_live_view 0.18.15) lib/phoenix_live_view/channel.ex:216: Phoenix.LiveView.Channel.handle_info/2
(stdlib 4.0.1) gen_server.erl:1120: :gen_server.try_dispatch/4
(stdlib 4.0.1) gen_server.erl:1197: :gen_server.handle_msg/6
(stdlib 4.0.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
ZachDaniel
ZachDaniel3y ago
I’m not sure about the error message, but exposing the calculation like in the other thread you mentioned is probably the best way to go about it. Basically there isn’t a great way to recalculate values live on a form, it’s typically something you need to do manually. Although I think it’s something we can have a utility for in the future.
Jason
JasonOP3y ago
Thank you. I will try!

Did you find this page helpful?