#328·stimulus

`connect` not picking up initial values of input elements (browser 'back' button)

Author: phylorCreated Sep 7, 2020Updated Jan 29, 2025

Hi there!

We stumbled upon unexpected behavior when using connect.

Scenario:

  1. We have a page with radio buttons
  2. The user selects a radio button
  3. The user submits the form
  4. The user uses the back button in her browser
  5. Stimulus' connect does not recognize the selected radio button

GIF of the behavior:

screengrab-20200907-1325

image

Stimulus controller
javascript
export default class extends Controller {
  static targets = ["buttons"]

  initialize() {
    console.group('initialize')
    console.log('target', this.buttonsTarget)
    console.log('selected radio button', this.buttonsTarget.querySelector(":scope input:checked"))
    console.groupEnd()
  }

  connect() {
    console.group('connect')
    console.log('target', this.buttonsTarget)
    console.log('selected radio button', this.buttonsTarget.querySelector(":scope input:checked"))
    console.groupEnd()

    let self = this
    setTimeout(function() {
      console.group('connect with timeout')
      console.log('target', self.buttonsTarget)
      console.log('selected radio button', self.buttonsTarget.querySelector(":scope input:checked"))
      console.groupEnd()
    }, 1)
  }

  loadEvent() {
    console.group('load@window')
    console.log('target', this.buttonsTarget)
    console.log('selected radio button', this.buttonsTarget.querySelector(":scope input:checked"))
    console.groupEnd()
  }
}
View
xml
<%= form_tag '/examples' do %>
  <div data-controller="radios" data-target="radios.buttons" data-action="load@window->radios#loadEvent">
    <div><%= radio_button_tag 'radios', 'a' %> a</div>
    <div><%= radio_button_tag 'radios', 'b' %> b</div>
  </div>

  <%= submit_tag %>
<% end %>

A demo Rails project is available on https://github.com/phylor/stimulus-connect-back-button.

Expected behavior:

The code below should evaluate to the selected radio button. It is null instead.

javascript
connect() {
  this.buttonsTarget.querySelector(":scope input:checked")
}

Workaround:

Use setTimeout within connect:

javascript
let self = this
setTimeout(function() {
  self.buttonsTarget.querySelector(":scope input:checked")
}, 1)

Browsers:

  • Chrome/qutebrowser: unexpected behavior, setTimeout workaround required
  • Firefox: seems to work as expected, even in initialize the selected radio button is found

I have to admit that I managed to get the expected behavior in Chrome as well. But really really seldom. Could be a race condition?

Questions

  • Is this just a bug in Chrome?
  • Is there something Stimulus could do to remedy the workaround?
  • Is there an entire different solution for this problem?