Guidance on Dynamic Filtering, Sorting, and Pagination
Hello Ash community,
I'm implementing standard filtering, sorting, and pagination features for my contacts module and have defined a read action as follows:
In my controller, I parse incoming parameters with default values:
I invoke the function as:
I'd like to understand how to pass these parameters to effectively filter, sort, and paginate the contacts list. Specifically:
- How can I apply a case-insensitive search filter to multiple attributes and only when search_query is present?
- What's the recommended way to implement dynamic sorting based on sort_by and sort_dir?
- How should I handle pagination using current_page?
- Are there best practices for sanitizing and validating these parameters before applying them?
Any guidance or examples on implementing these features would be greatly appreciated.
Thanks in advance!
14 Replies
I think first thing your function invocation is not right. It should be something like:
Contacts.list_contacts!(params, actor: current_user)
, where params is a map.
If you want to apply case-insensitive search you'll need a preparation on your read action.
https://hexdocs.pm/ash/Ash.Query.html#sort/3 you can see how to pass the options to sort here. I tend to use the "-name" syntax.
To call your action you'll do: Contacts.list_contacts!(%{search: "something to search", sort: "-name,phone,-date_of_birth"}, actor: current_user, page: page_config)
Now thing like pagination are handled with the page
option:
Contacts.list_contacts!(params, actor: current_user, page: page_config)
where page_config
depends wether you're using a keyset or an offset pagination.
https://hexdocs.pm/ash/pagination.html#offset-pagination-1 please read all this docs to better understand how to use pagination.Look into
Ash.Query.filter_input
and Ash.Query.sort_input
🙂Hi @franckstifler , thanks for the reply. Unfortunately, the code you provided has invalid syntax. It did give me some ideas though
I am trying this:
But doesn't seem to work either. Any ideas @ZachDaniel?
Will need more info than "doesn't work" 🙂
Hope this helps

My action:
How I'm calling it:
Ah, right
Use
^query.arguments.search
Great. It's working now. I'll continue with the remaining features and let you know how it goes. Thanks!
Hey Zach. I've gotten this far with everything working smoothly:
And my controller:
I believe there's still some room for improvement though. Is it possible to transform the paginated data within the action itself, so that I can return the transformed data directly and avoid handling the transformation in the controller?
You'd need to use a generic action to do some additional processing of the paginated results
I got it working like this:
This is really good.
One question though, what should I look into so I can make this logic reusable for other resources?
In a real-world application I'm developing, I'll have about five different resources that will require the same dynamic filtering, sorting, pagination and serialization.
You can extract that into a shared action implementation, which you then provide options to potentially
Alright. This is my implementation:
And I'm using it like this:
Love it. I think this is a beautiful piece of reusable action.
Please tell me if you see something that it's worth refactoring otherwise I'll be good to go
Looks great!
Awesome! I'll tag this as solved.
Thanks a lot for the support Zach.