Apply a filter

Hi again…
In a list of users I try to filter by city.
#index

     <%= form_for @conn, user_path(@conn, :index), [method: :get, as: :search], fn f -> %>
        <%= label f, :users_city, "Suche nach Cities" %>
        <%= select f, :users_city, Enum.map(@users, &{&1.city, &1.city} ) %>
        <%= submit "Filter"%>
      <% end %>

#user_controller

      def index(conn, params) do
    city = get_in(params, ["search", "users_city"])

    users = Accounts.list_users()
    render(conn, "index.html", users: users)
  end

#accounts

    def list_users do
    User
    #|> where([p], p.city == "München")
    |> Repo.all()
    |> Repo.preload(:credential)

  end

This works but sure I want send parameter…
I can’t find recent tut thats why I am asking here…

  1. The complete list should be shown if no filter is applied
  2. Only users from the selected city are shown id select field / Filter applied
    (3. the select field should show all cities all times…)

Would be great to get some help.
I have tried something like that with no success:

  def find_citiy(query, year) when is_nil(year) or byte_size(year) == 0 do
    query
  end
  def find_city(query, city) do
    from user in query,
    where: user.city == ^city
  end

If you know a 1.3 tut …link pls.

Thanks

Could you please wrap your code blocks in ```? Or indent by 4 (I think) spaces.

```
your code
```
1 Like

I edited the post to add formatting, much easier to read now. :slight_smile:

1 Like

I would do something like:

def list_users(city \\ nil) do
  User
  |> filter_city(city)
  |> Repo.all()
  |> Repo.preload(:credential)
end

defp filter_city(query, nil), do: query
defp filter_city(query, city), do: where(query, [p], p.city in ^city)

And in controller:

def index(conn, params) do
  city = get_in(params, ["search", "users_city"])

  users = Accounts.list_users(city)
  render(conn, "index.html", users: users)
end
1 Like

And when it gets complex, I normally do something like:

def list_users(filter \\ %{}) do
  User
  |> apply_filter(filter)
  |> Repo.all()
  |> Repo.preload(:credential)
end

defp apply_filter(query, filter) do 
  query
  |> filter_city(filter["city"])
  |> where([p], p.inserted_at > ^filter["from"])
end

defp filter_city(query, nil), do: query
defp filter_city(query, city), do: where(query, [p], p.city in ^city)

And in controller:

def index(conn, params) do
  users = Accounts.list_users(params["search"])
  render(conn, "index.html", users: users)
end
3 Likes

Thanks… nice && good looking code…just one more.

Right now I just have a link to show all, works… but is there a way to clearFilter with a button?

<%= submit "Filter", class: "button is-info"%>
<%= link "All", to: user_path(@conn, :index), class: "button is-primary" %>
1 Like

I always do the same you did, the only difference is that I call the link "Clear filter" :slight_smile:

1 Like