Use a custom operator on FilterForm

Is it possible to expand FilterForm to allow other types of operators like using ilike or <% during filtering? I believe that this item will give a solution for that https://github.com/ash-project/ash/issues/374 but AFAIK this is not done yet. So, for now is there a workaround?
GitHub
Custom predicates & operators · Issue #374 · ash-project/ash
These would be exposed to the expression syntax in code, and can be made available over api extensions as well. I'm thinking something like this: support a custom configured list of functions t...
8 Replies
ZachDaniel
ZachDaniel3y ago
You can add calculations to the resource and filter on the calculation The filterform supports “arguments” which are the arguments on the calculation.
Blibs
BlibsOP3y ago
Can you give me an example on how to use these arguments? This is what I tried but i can't figure out how to pass the argument to the filter form:
# On my Property resource:


calculations do
calculate :full_address,
:string,
expr(
house_number <> " " <> street <> " - " <> city <> ", " <> state <> " - " <> zip
)

calculate :fuzzy_full_address, :string, expr(fragment("? <% ?", ^arg(:value), full_address)) do
argument :value, :string, allow_nil?: false
end
end
# On my Property resource:


calculations do
calculate :full_address,
:string,
expr(
house_number <> " " <> street <> " - " <> city <> ", " <> state <> " - " <> zip
)

calculate :fuzzy_full_address, :string, expr(fragment("? <% ?", ^arg(:value), full_address)) do
argument :value, :string, allow_nil?: false
end
end
alias AshPhoenix.FilterForm
alias Marketplace.Markets.Property

f = FilterForm.new(Property)

f = FilterForm.add_predicate(f, :fuzzy_full_address, :and, "Blibs")
alias AshPhoenix.FilterForm
alias Marketplace.Markets.Property

f = FilterForm.new(Property)

f = FilterForm.add_predicate(f, :fuzzy_full_address, :and, "Blibs")
ZachDaniel
ZachDaniel3y ago
If you want to provide arguments when you add_predicate that might take a small addition to AshPhoenix.FilterForm but inside the predicate form would do something like this:
#inputs_for :arguments
<.input ... field={{argument_form, :argument_name}} />
#inputs_for :arguments
<.input ... field={{argument_form, :argument_name}} />
ZachDaniel
ZachDaniel3y ago
GitHub
ash_phoenix/filter_form.ex at v1.2.13 · ash-project/ash_phoenix
https://hexdocs.pm/ash_phoenix. Contribute to ash-project/ash_phoenix development by creating an account on GitHub.
Blibs
BlibsOP3y ago
I can try to create a PR for this, but I'm not sure what the opt :arguments would take, the argument, at least for the calculation I did, should be the value that the user is typing in the input anyway
ZachDaniel
ZachDaniel3y ago
Got it, then you just need to add the predicate, and then when rendering that predicate you'd add inputs for the arguments
Blibs
BlibsOP3y ago
Yeah, I can't figure out how exactly I should be doing that.. I tried adding the component value inside the arguments struct manually:
alias AshPhoenix.FilterForm
alias Marketplace.Markets.Property

f = FilterForm.new(Property)

f = FilterForm.add_predicate(f, :fuzzy_full_address, :and, "Blibs")

components =
Enum.map(f.components, fn
%{field: :fuzzy_full_address} = component ->
# Copy component value to arguments
component =
Map.update!(component, :arguments, fn arguments ->
%{arguments | input: %{value: component.value}}
end)

component

component ->
component
end)

f = %{f | components: components}


{:ok, query} = FilterForm.filter(Property, f)
alias AshPhoenix.FilterForm
alias Marketplace.Markets.Property

f = FilterForm.new(Property)

f = FilterForm.add_predicate(f, :fuzzy_full_address, :and, "Blibs")

components =
Enum.map(f.components, fn
%{field: :fuzzy_full_address} = component ->
# Copy component value to arguments
component =
Map.update!(component, :arguments, fn arguments ->
%{arguments | input: %{value: component.value}}
end)

component

component ->
component
end)

f = %{f | components: components}


{:ok, query} = FilterForm.filter(Property, f)
But this doesn't work, not only seems like a very ugly hack, but it will also keep the :and operator and make the query break when running it. 🤔
ZachDaniel
ZachDaniel3y ago
🤔 So there isn't a way to do it programatically like I mentioned (that would need to be added to the filter form add_predicate) What you would be doing is adding them as inputs in the html form

Did you find this page helpful?