Skip to content

Instantly share code, notes, and snippets.

@julianrubisch
Created December 3, 2021 17:39
Show Gist options
  • Save julianrubisch/7e6742945be9d21b90f60ce4cb558d9f to your computer and use it in GitHub Desktop.
Save julianrubisch/7e6742945be9d21b90f60ce4cb558d9f to your computer and use it in GitHub Desktop.
$ bundle add pagy
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
include Pagy::Backend
# ...
end
// app/javascript/controllers/board_infinite_scroll_controller.js
import ApplicationController from "./application_controller";
export default class extends ApplicationController {
static targets = ["button"];
connect() {
super.connect();
}
loadMore(event) {
event.preventDefault();
this.buttonTarget.disabled = true;
this.buttonTarget.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
this.stimulate("BoardInfiniteScroll#load_more", this.buttonTarget);
}
}
// app/javascript/controllers/board_infinite_scroll_controller.js
import ApplicationController from "./application_controller";
import { useIntersection } from "stimulus-use";
export default class extends ApplicationController {
static targets = ["button"];
connect() {
super.connect();
useIntersection(this, { element: this.buttonTarget });
}
appear() {
this.buttonTarget.disabled = true;
this.buttonTarget.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
this.stimulate("BoardInfiniteScroll#load_more", this.buttonTarget);
}
}
# app/reflexes/board_infinite_scroll_reflex.rb
class BoardInfiniteScrollReflex < InfiniteScrollReflex
include Filterable
before_reflex do
@pagy, @collection = pagy filter_for("Embed").apply!(board.embeds).order(created_at: :asc), items: 2, page: page
end
def selector
"#add-embed-button"
end
def board
element.signed[:board_sgid]
end
end
<div id="<%= dom_id(board, :load_more) %>" data-controller="board-infinite-scroll">
<% if pagy.page < pagy.last %>
<button
data-next-page="<%= pagy.page + 1 %>"
data-board-sgid="<%= board.to_sgid.to_s %>"
data-board-infinite-scroll-target="button"
data-reflex-root="#<%= dom_id(board, :load_more) %>"
class="inline-flex justify-center w-full py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-lime-600 hover:bg-lime-700 focus:outline-none focus:ring-2 focus :ring-offset-2 focus:ring-lime-500">Load more embeds</button>
<% end %>
</div>
<div id="<%= dom_id(board, :load_more) %>" data-controller="board-infinite-scroll">
<% if pagy.page < pagy.last %>
<button
data-action="board-infinite-scroll#loadMore"
data-next-page="<%= pagy.page + 1 %>"
data-board-sgid="<%= board.to_sgid.to_s %>"
data-board-infinite-scroll-target="button"
data-reflex-root="#<%= dom_id(board, :load_more) %>">
Load more embeds
</button>
<% end %>
</div>
<!-- app/views/boards/_board.html.erb -->
<!-- embed grid -->
<div id="<%= dom_id(board, :load_more) %>">
<% if pagy.page < pagy.last %>
<button
data-reflex="click->InfiniteScroll#load_more"
data-next-page="<%= pagy.page + 1 %>"
data-board-sgid="<%= board.to_sgid.to_s %>"
data-reflex-root="#<%= dom_id(board, :load_more) %>">
Load more embeds
</button>
<% end %>
</div>
<!-- app/views/boards/_board.html.erb -->
<!-- embed grid -->
<% if pagy.page < pagy.last %>
<button>Load more embeds</button>
<% end %>
# app/controllers/boards_controller.rb
class BoardsController < ApplicationController
# ...
def show
@embed_templates = current_user.embed_templates
@pagy, @embeds = pagy filter_for("Embed").apply!(@board.embeds).order(created_at: :asc), items: 2 unless @stimulus_reflex
end
# ...
end
$ bin/rails g stimulus_reflex InfiniteScroll load_more
# app/reflexes/infinite_scroll_reflex.rb
class InfiniteScrollReflex < ApplicationReflex
include Filterable
include Pagy::Backend
def load_more
@pagy, embeds = pagy filter_for("Embed").apply!(board.embeds).order(created_at: :asc), items: 2, page: page
cable_ready.insert_adjacent_html(
selector: "#add-embed-button",
html: render(partial: "embeds/embed", collection: embeds, locals: {user: current_user}),
position: "beforebegin"
)
end
def page
element.dataset.next_page
end
def board
element.signed[:board_sgid]
end
end
# app/reflexes/infinite_scroll_reflex.rb
class InfiniteScrollReflex < ApplicationReflex
include Filterable
include Pagy::Backend
attr_reader :collection
before_reflex do
@pagy, @collection = pagy filter_for("Embed").apply!(board.embeds).order(created_at: :asc), items: 2, page: page
end
def load_more
cable_ready.insert_adjacent_html(
selector: selector,
html: render(partial: partial_path, collection: collection, locals: locals),
position: position
)
end
def page
element.dataset.next_page
end
def partial_path
collection.first.to_partial_path
end
def locals
{user: current_user}
end
def position
"beforebegin"
end
def selector
"#add-embed-button"
end
def board
element.signed[:board_sgid]
end
end
# app/reflexes/infinite_scroll_reflex.rb
class InfiniteScrollReflex < ApplicationReflex
include Pagy::Backend
attr_reader :collection
def load_more
cable_ready.insert_adjacent_html(
selector: selector,
html: render(partial: partial_path, collection: collection, locals: locals),
position: position
)
end
def page
element.dataset.next_page
end
def partial_path
collection.first.to_partial_path
end
def locals
{user: current_user}
end
def position
"beforebegin"
end
def selector
raise NotImplementedError
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment