Skip to content

Commit fef4085

Browse files
committed
Refactor currency field to use masked input
1 parent beb5842 commit fef4085

File tree

1 file changed

+35
-39
lines changed

1 file changed

+35
-39
lines changed

lib/backpex/fields/currency.ex

Lines changed: 35 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,23 @@ defmodule Backpex.Fields.Currency do
77
throttle: [
88
doc: "Timeout value (in milliseconds) or function that receives the assigns.",
99
type: {:or, [:pos_integer, {:fun, 1}]}
10+
],
11+
unit: [
12+
doc: "Unit to display with the currency value, e.g. '€'.",
13+
type: :string,
14+
default: "€"
15+
],
16+
radix: [
17+
doc:
18+
"Character used as the decimal separator, e.g. ',' or '.'. Make sure this value matches the one you've configured in your Money library.",
19+
type: :string,
20+
default: ","
21+
],
22+
thousands_separator: [
23+
doc:
24+
"Character used as the thousands separator, e.g. '.' or ','. Make sure this value matches the one you've configured in your Money library.",
25+
type: :string,
26+
default: "."
1027
]
1128
]
1229

@@ -21,16 +38,14 @@ defmodule Backpex.Fields.Currency do
2138
2239
## Schema
2340
24-
`Backpex.Ecto.Amount.Type` provides a type for Ecto to store a amount. The underlying data type should be an integer.
25-
For a full list of configuration options see: https://hexdocs.pm/money/Money.html#module-configuration
41+
Backpex expects you to use a Money library or a similar approach for handling currency values and dumping / casting them correctly in your database schema.
2642
27-
schema "article" do
28-
field :price, Backpex.Ecto.Amount.Type
29-
...
30-
end
43+
Ensure that your schema field is set up to handle the currency type appropriately.
44+
45+
For example, if you are using the [Money](https://hex.pm/packages/money) library, your schema might look like this:
3146
3247
schema "article" do
33-
field :price, Backpex.Ecto.Amount.Type, currency: :EUR, opts: [separator: ".", delimiter: ","]
48+
field :price, Money.Ecto.Amount.Type
3449
...
3550
end
3651
@@ -41,46 +56,45 @@ defmodule Backpex.Fields.Currency do
4156
[
4257
price: %{
4358
module: Backpex.Fields.Currency,
44-
label: "Price"
59+
label: "Price",
60+
unit: "€",
61+
radix: ",",
62+
thousands_separator: "."
4563
}
4664
]
4765
end
4866
"""
4967
use Backpex.Field, config_schema: @config_schema
68+
5069
import Ecto.Query
51-
alias Backpex.Ecto.Amount.Type
5270

5371
@impl Backpex.Field
5472
def render_value(assigns) do
55-
schema = assigns.live_resource.adapter_config(:schema)
56-
assigns = assign(assigns, :casted_value, maybe_cast_value(assigns.name, schema, assigns.value))
57-
5873
~H"""
5974
<p class={@live_action in [:index, :resource_action] && "truncate"}>
60-
{@casted_value}
75+
{@value}
6176
</p>
6277
"""
6378
end
6479

6580
@impl Backpex.Field
6681
def render_form(assigns) do
67-
assigns = assign(assigns, :casted_value, maybe_cast_form(PhoenixForm.input_value(assigns.form, assigns.name)))
68-
6982
~H"""
7083
<div>
7184
<Layout.field_container>
7285
<:label align={Backpex.Field.align_label(@field_options, assigns)}>
7386
<Layout.input_label text={@field_options[:label]} />
7487
</:label>
75-
<BackpexForm.input
76-
type="number"
88+
<BackpexForm.masked_input
89+
type="text"
7790
field={@form[@name]}
78-
value={@casted_value}
91+
translate_error_fun={Backpex.Field.translate_error_fun(@field_options, assigns)}
7992
help_text={Backpex.Field.help_text(@field_options, assigns)}
8093
phx-debounce={Backpex.Field.debounce(@field_options, assigns)}
8194
phx-throttle={Backpex.Field.throttle(@field_options, assigns)}
82-
step=".01"
83-
min="0"
95+
unit={@field_options[:unit]}
96+
radix={@field_options[:radix]}
97+
thousands_separator={@field_options[:thousands_separator]}
8498
/>
8599
</Layout.field_container>
86100
</div>
@@ -91,25 +105,7 @@ defmodule Backpex.Fields.Currency do
91105
def search_condition(schema_name, field_name, search_string) do
92106
dynamic(
93107
[{^schema_name, schema_name}],
94-
ilike(fragment("CAST(? AS TEXT)", schema_name |> field(^field_name)), ^search_string)
108+
ilike(fragment("CAST(? AS TEXT)", field(schema_name, ^field_name)), ^search_string)
95109
)
96110
end
97-
98-
defp maybe_cast_value(field_name, schema, value) do
99-
type = schema.__schema__(:type, field_name) || schema.__schema__(:virtual_type, field_name)
100-
101-
case type do
102-
{:parameterized, Backpex.Ecto.Amount.Type, opts} ->
103-
{:ok, money} = Type.cast(value, opts)
104-
105-
Money.to_string(money, Keyword.get(opts, :opts, []))
106-
107-
_type ->
108-
value
109-
end
110-
end
111-
112-
defp maybe_cast_form(val) when is_binary(val), do: val
113-
defp maybe_cast_form(nil), do: Decimal.new("0.00")
114-
defp maybe_cast_form(%Money{} = value), do: Money.to_decimal(value)
115111
end

0 commit comments

Comments
 (0)