div(data-controller="counter")
  fieldset(data-controller="counter")
    legend GroupA
    - for (let x = 0; x < 5; x++)
      label
        input(
          type="checkbox"
          data-counter-target="item"
          data-action="counter#update"
        )
        span=`something_${x}`
    div
      span.count(data-counter-target="val") 0
      span item checked!
  fieldset(data-controller="counter")
    legend GroupB
    - for (let x = 0; x < 5; x++)
      label
        input(
          type="checkbox"
          data-counter-target="item"
          data-action="counter#update"
        )
        span=`something_${x}`
    div
      span.count(data-counter-target="val") 0
      span item checked!
  div
    span totallay
    span.count(data-counter-target="val") 0
    span item checked!
    
p.note
  | In this example, the overall number of checks is not updated.
  | This is because the concept of scope applies to the Target API.
View Compiled
label {
  display: block;
}
label > * { vertical-align: middle; }
.count {
  margin-right: .5em;
  font-weight: bold;
  color: red;
}
span + .count {
  margin-left: .5em;
}

p.note {
  padding: 10px;
  background: #f4f4f4;
  border-radius: 4px;
}
import {Application, Controller} from "https://cdn.skypack.dev/@hotwired/stimulus@3.2.1";
const app = Application.start();

app.register('counter', class extends Controller {
  static targets = ['item', 'val'];
  
  update() {
    this.valTarget.textContent = String(this.checkedItem.length);
  }
  
  get checkedItem() {
    return this.itemTargets.filter(item => item.checked)
  }
})
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.