[Stimulus] Dispatching bubbling event in nested identical controller doesn't work

Hi,
Given this controller called nestedctrl

import {Controller} from '@hotwired/stimulus';

export default class extends Controller {
    static values = {
        counter: {type: Number, default: 0},
        childAmount: {type: Number, default: 0},
    }

    increment(event) {
        const amount = 1;
        this.counterValue = this.counterValue + amount;
        this.dispatch('addedToCounter', {detail: {amount: amount}});
    }

    addChildAmount({detail: {amount}}) {
        this.childAmountValue = this.childAmountValue + amount;
    }
}

and this HTML

<div data-controller="nestedctrl" 
     data-nestedctrl-child-amount-value="5" 
     data-action="nestedctrl:addedToCounter->nestedctrl#addChildAmount"
>
    <div data-controller="nestedctrl" data-nestedctrl-counter-value="2">
        <button data-action="click->nestedctrl#increment">Bump up</button>
    </div>
    <div data-controller="nestedctrl" data-nestedctrl-counter-value="3">
        <button data-action="click->nestedctrl#increment">Bump up</button>
    </div>
</div>

It’s a multi level nested controllers, all the same. There can be more than 2 level of controllers, I keep 2 to stay readable.
On each button click, the counter-value of the closest controller is incremented.
An event is dispatched.
I want the event to be bubbled up to the upper level controller and handled by it in order to aggregate the counter value of each child.

But as they are the same “nestedctrl” controller, the event is not handled.

It seems that the problem lie in Scope::containsElement

  containsElement = (element: Element): boolean => {
    return element.closest(this.controllerSelector) === this.element
  }

When this method is called, controllerSelector is [data-controller=nestedctrl], and the closest element to the emitting element is itself, and not the parent one with the action.

The event cannot be bubbled up and handled by a parent which is the same controller as the dispatcher.
The same problem occurs when an event is dispatched by another controller inside a nested structure.

Is there any workaround or is it a bug

Is this a copy/paste from your code? Because if it is, you declared const ’amout’ (a typo) and then referred to ‘amount’ later.

Walter

no, it’s not a pure copy. The amount var was added directly in the board.

Still, this is not what prevent the event to be handled.

I’ve found a workaround that seems to work.
I have to change the target in the dispatch in order to trick the containsElement method:
Using the parent element of the controller’s element, the element.closest() call do not stop and bubble up as needed.

    increment(event) {
        const amount = 1;
        this.counterValue = this.counterValue + amount;
        this.dispatch('addedToCounter', {target: this.element.parentElement, detail: {amount: amount}});
    }