import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["master", "item"]
toggleAll() {
const checked = this.masterTarget.checked
this.itemTargets.forEach((i) => (i.checked = checked))
}
updateMaster() {
const checked = this.itemTargets.filter((i) => i.checked).length
this.masterTarget.indeterminate = checked > 0 && checked < this.itemTargets.length
this.masterTarget.checked = checked === this.itemTargets.length
}
}
<%= form_with url: admin_snips_bulk_path, method: :post, data: { controller: "bulk-select" } do %>
<label>
<input type="checkbox" data-bulk-select-target="master" data-action="bulk-select#toggleAll" />
Select all
</label>
<% @snips.each do |snip| %>
<label>
<input type="checkbox" name="snip_ids[]" value="<%= snip.id %>"
data-bulk-select-target="item" data-action="bulk-select#updateMaster" />
<%= snip.title %>
</label>
<% end %>
<%= submit_tag "Archive", class: "btn" %>
<% end %>
For batch operations, Stimulus can manage the UI state (select all, indeterminate checkbox) while Turbo submits a regular form. This keeps the server in charge of authorization and the UI simple.