hotwired / stimulus

A modest JavaScript framework for the HTML you already have
https://stimulus.hotwired.dev/
MIT License
12.73k stars 425 forks source link

This.element is showing a previous (cached?) version of the DOM element #774

Closed sromano closed 5 months ago

sromano commented 5 months ago

(First of all, thanks and great work)

Short description this.element is showing a dom that is not part of HTML

More detail description I can see at the HTML (see Elements) that the dom element does not include data-information-referral--sessions--client-caller-selected-client-person-id-value="2492" (I confirm this is the only element in the HTML, I don't have any duplicate and no place in the HTML you can find data-information-referral--sessions--client-caller-selected-client-person-id-value="2492")

However, if you look at this.element and this.selectedClientPersonIdValue, it is showing information from a previous page experience. It's not reading current DOM. I made a breakpoint to catch it

Screenshot 2024-05-31 at 3 28 59 PM

Expected behavior this.element should not include any data-information-referral--sessions--client-caller-selected-client-person-id-value="2492" as the HTML has. And this.selectedClientPersonIdValue should be nil

Fragment of the Controller

export default class extends CustomAutocomplete {
  static targets = ['personFieldContainer', 'personField']
  static values = {
    selectedClientPersonId: String,
    selectedContactCallerPersonId: String,
    selectedProfessionalCallerPersonId: String,
  }

  connect() {
    this.selectedClientPersonId = this.selectedClientPersonIdValue
    this.selectedContactCallerPersonId = this.selectedContactCallerPersonIdValue
    this.selectedProfessionalCallerPersonId = this.selectedProfessionalCallerPersonIdValue

    this.selectPerson = this.selectPerson.bind(this)
    this.unselectPerson = this.unselectPerson.bind(this)
    this.clearOrUnScopeCallerField = this.clearOrUnScopeCallerField.bind(this)

    this.element.addEventListener('autocomplete.change', this.selectPerson)
    this.element.addEventListener('autocomplete.clear', this.unselectPerson)
    document.addEventListener('clear-callers-field', this.clearOrUnScopeCallerField)
  }

  disconnect() {
    this.element.removeEventListener('autocomplete.change', this.selectPerson)
    this.element.removeEventListener('autocomplete.clear', this.unselectPerson)
    this.element.removeEventListener('clear-callers-field', this.clearOrUnScopeCallerField)
   }

   ...
}  

Browser Google Chrome Version 125.0.6422.113 (Official Build) (arm64)

sromano commented 5 months ago

The event listener was added to the document and not removed. That seems to cause a previous version of document to still be listening besides new document being loaded and event listener added to the new one. Fixed by correctly removing the listener from document in disconnect.

This probably is undefined behaviour