Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

useClickOutside: [bug?] multiple instances of controller #193

Open
pySilver opened this issue May 4, 2022 · 7 comments
Open

useClickOutside: [bug?] multiple instances of controller #193

pySilver opened this issue May 4, 2022 · 7 comments

Comments

@pySilver
Copy link

pySilver commented May 4, 2022

Hi!

I have 2 instances of widget controller called search-form. One instance is used for mobile view and the other for larger screens. Both of them are placed in a totally different areas of a page (no parent-child relation). Both of them are implemented as:

  connect() {
    useClickOutside(this);
  }

  clickOutside(event) {
    event.preventDefault();
    this._setState(false); // hide page backdrop, suggestions popup and so on
  }

Im observing the following unexpected behaviour where mobile instance of controller is capturing outside-clicks and triggers clickOutside method of all controller instances . I'd expect it will call this method for its own instance, not all of them.

Is this a bug or expected behaviour?

@marcoroth
Copy link
Member

marcoroth commented May 6, 2022

Hey @pySilver, thanks for opening this issue!

I think the behavior you are describing makes sense and is expected.

The clickOutside callback, as the name suggests, always gets triggered if you click outside the controller element of that instance. Now if you click on an element outside of both controller instances each instance is technically seeing that as a click outside their controller element.

useClickOutside

This applies unless you are explicitly passing a different element as an option to the useClickOutside mixin.

Or am I misunderstanding what you are describing?

@pySilver
Copy link
Author

pySilver commented May 6, 2022

Hello @marcoroth! Thanks for your reply. Yes, I think I'm observing something else. Let me refer your example.

<div id="desktop-view" data-controller="search-form">
  <div data-search-form-target="suggestions">search suggestions are shown here when form is active</div>
</div>
...
<div id="mobile-view" data-controller="search-form">
  <div data-search-form-target="suggestions">search suggestions are shown here when form is active</div>
</div>
  // search-form controller
  connect() {
    useClickOutside(this);
  }

  clickOutside(event) {
    console.log("im triggered", this.element, this.suggestionsTarget);
    event.preventDefault();
    this._clearSuggestions();
  }

  _clearSuggestions() {
    this.suggestionsTarget.innerHTML = "";
  }

Now click inside the area of the desktop-view is, as expected, triggers clickOutside for the mobile-view as they do not intersect. As callback is triggered for mobile-view I'd expect that this.suggestionsTarget of the mobile-view will be closed but instead both of suggestion boxes are being affected - within desktop-view and mobile-view. That is really strange since console log of a given setup clearly shows that this.element & this.suggestionsTarget belong to mobile-view

So it doesn't really look as stimulus-use issue here, but more stimulus itself (?)

@pySilver
Copy link
Author

pySilver commented May 6, 2022

Funny. In fact if I instead use this code:

  _clearSuggestions() {
    this.suggestionsTarget.classList.add("hidden");
  }

I'm seeing that console.log("im triggered", this.element, this.suggestionsTarget); still reports proper elements that supposed to be affected (this.element belongs to mobile-view as well as this.suggestionsTarget). However the DOM shows that hidden class has been added to the desktop-view only. And I have no explanation why.

@pySilver
Copy link
Author

@marcoroth any idea what may cause this or how can I debug the issue?

@marcoroth
Copy link
Member

marcoroth commented May 10, 2022

@pySilver The only thing that directly comes to mind is that you might be missing a closing </div> somewhere and that it somehow is seeing both targets as targets of the first controller.

You could start by logging and see if this.suggestionsTarget and this.suggestionsTargets are the expected elements in the connect() function.

One thing that also often helps is to try to re-create this behavior in a minimal setup and see if you can see the same behavior there.

Otherwise I don't see anything obvious why it would behave that way.

@marcoroth
Copy link
Member

Hey @pySilver, I'm just checking in. Did you have any success debugging your issue?

@pySilver
Copy link
Author

pySilver commented Aug 6, 2022

Hey @marcorot! Unfortunately not. I've had to change the logic a little bit to mitigate the issue.

@marcoroth marcoroth changed the title [bug?] useClickOutside multiple instances of controller useClickOutside: [bug?] multiple instances of controller Aug 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants