Hello folks! I recently added search and sort features to my application. Today I tried to add pagination for my index page. Pagination works. However, when I use the search or sort feature it does not do what I expect. When I search it displays the correct number of pages but when I click on the next page it just displays paginated all books in the DB. When I use sorting it shows sorted results on the first page but again, the second page is just a second page of paginated records without any order. Could you please look at the code and help me to solve this problem? I’m guessing that my code is far from perfect but I am still learning and I’m open to any suggestions to make changes to the code.
I have followed the hexdocs instructions for scrivener_ecto and scrivener_html. I attach my index code from book_controller
.
def index(conn, params) do
page =
Bookstore.Inventory.list_books(params)
|> BookstoreWeb.ViewHelpers.sort_by_params(params, @book_sort_fields)
|> Repo.paginate(params)
# |> Repo.preload(:author)
# |> Repo.preload(:category)
# |> Repo.preload(:publisher)
render(conn, "index.html", books: page.entries, page: page)
end
EDIT: I got working search and paginating results with:
Book index
<%= pagination_links @page, query: @query, next: "Next", previous: "Prev" %>
Book controller
def index(conn, params) do
books = Bookstore.Inventory.list_books(params)
search_term =
get_in(params, ["query"])
|> BookstoreWeb.ViewHelpers.sort_by_params(params, @book_sort_fields)
# |> Repo.preload(:author)
# |> Repo.preload(:category)
# |> Repo.preload(:publisher)
render(conn, "index.html", books: books.entries, page: books, query: search_term)
end
Inventory
def list_books(params) do
search_term = get_in(params, ["query"])
Book
|> Bookstore.Inventory.Book.search(search_term)
|> preload(:category)
|> preload(:author)
|> preload(:publisher)
|> Repo.paginate(params)
end
However, when I want to sort search results I got this error:
# unknown bind name
:book in query:
When I do not use search and just try to sort books I see this error:
protocol Ecto.Queryable not implemented for nil of type Atom, the given module does not exist. This protocol is implemented for the following type(s): BitString, Tuple, Ecto.Query, Ecto.Query, Ecto.SubQuery, BitString, Tuple, Atom, Ecto.SubQuery, Atom
Both errors point to:
defp do_sort_by_params(qs, val, ord, allowed) do
if val in allowed do
[binding, name] = val |> String.split("__") |> Enum.map(&String.to_atom/1)
qs |> order_by([{^binding, t}], [{^ord, field(t, ^name)}]) #THIS LINE
else
qs
end
end
EDIT 2:
I have been tweaking the code one way and another but I’m stuck with Search + pagination working but when I want to sort found books/all books records on the first page are correct. However, on every other page sorting does not apply. After I search and use sort the URL looks like that:
/books?order_by=-book__title&query=se
When I go to the second page order_by is not passed.
books?query=se&page=2
I will attach more code if needed.