Stimulus Discourse

Accessing Targets Conditionally


#1

I have a controller that needs to access a collection of checkboxes that are currently checked:

  get checked(){
    return this.element.querySelectorAll('input[type=checkbox]:checked')
  }

Is this the right Stimulus approach? I could make each checkbox a target, but I would still need to grab only those checkboxes that are currently checked.


#2

Making them a target and filtering out unchecked checkboxes would probably be the way to go:

get checked() {
  return this.checkboxTargets.filter(checkbox => checkbox.checked)
}

#3

Thanks Kasper! So I need to slice and dice those targets a few different ways. For example:

// selected checkboxes with a data type of cash
this.element.querySelectorAll('input[type=checkbox]:checked[data-type="cash"]')

// selected checkboxes with a data type of check
this.element.querySelectorAll('input[type=checkbox]:checked[data-type="check"]')

So for each of these, would you recommend moving away from the querySelectorAll and instead use the filter method?

I could change up my targets and do it like this:

this.checkCheckboxTargets.filter(checkbox => checkbox.checked)
this.cashCheckboxTargets.filter(checkbox => checkbox.checked)

#4

Glad I could help! :slight_smile: Yes, I would access the checkboxes as Stimulus targets instead of querying them manually.

If you have the option to differentiate the targets in the view based on their type, your suggested strategy works perfectly:

<input data-type="check" data-target="controller-name.checkCheckbox" ... >
<input data-type="cash" data-target="controller-name.cashCheckbox" ... >

Otherwise you’ll have to add an extra filter requirement to your properties:

get checkedCheck() {
  return this.checkboxTargets.filter(checkbox => {
    return checkbox.checked && checkbox.dataset.type === 'check'
  })
}

get checkedCash() {
  return this.checkboxTargets.filter(checkbox => {
    return checkbox.checked && checkbox.dataset.type === 'cash'
  })
}

Or DRY it up a bit, if you still need to access all checked checkboxes regardless of their type:

get checkedCheck() {
  return this.checked.filter(checkbox => checkbox.dataset.type === 'check')
}

get checkedCash() {
  return this.checked.filter(checkbox => checkbox.dataset.type === 'cash')
}

get checked() {
  return this.checkboxTargets.filter(checkbox => checkbox.checked)
}