Skip to content

Conversation

@daFish
Copy link
Contributor

@daFish daFish commented Oct 31, 2025

Q A
Bug fix? yes
New feature? no
Deprecations? no
Documentation? no
Issues Fix #2623
License MIT

Problem

When Autocomplete elements are removed and re-added to the DOM (e.g., with Turbo navigation), a race condition causes
"Tom Select already initialized on this element" error.

Root Cause

disconnect() destroys TomSelect but leaves this.tomSelect pointing to the destroyed instance. If urlValueChanged()
fires before connect() (during re-attachment), it calls resetTomSelect() on the stale reference, triggering
double-initialization.

Impact

  • Affects: Users with Turbo navigation, especially on mobile (Safari iOS)
  • Symptoms: "Tom Select already initialized" console errors during navigation
  • Fix: Single line addition prevents the race condition
  • Risk: None - only affects the disconnect cleanup path

@carsonbot carsonbot added Bug Bug Fix Status: Needs Review Needs to be reviewed labels Oct 31, 2025
@carsonbot carsonbot changed the title fix(autocomplete): clear tomselect instance to avoid double initialization fix(autocomplete): clear tomselect instance to avoid double initialization Oct 31, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Oct 31, 2025

📊 Packages dist files size difference

Thanks for the PR! Here is the difference in size of the packages dist files between the base branch and the PR.
Please review the changes and make sure they are expected.

FileBefore (Size / Gzip)After (Size / Gzip)
Autocomplete
controller.d.ts 1.95 kB / 656 B 1.96 kB+1% 📈 / 666 B+2% 📈
controller.js 15.02 kB / 3.88 kB 15.2 kB+1% 📈 / 3.91 kB+1% 📈

@daFish daFish changed the title fix(autocomplete): clear tomselect instance to avoid double initialization [Autocomplete] clear tomselect instance to avoid double initialization Oct 31, 2025
@daFish daFish force-pushed the fix/autocomplete-tomselect-cleanup branch 2 times, most recently from 4cac269 to 10ac03b Compare October 31, 2025 18:51
@daFish daFish marked this pull request as draft October 31, 2025 18:51
@daFish daFish force-pushed the fix/autocomplete-tomselect-cleanup branch 3 times, most recently from 5e5a833 to 1a899ea Compare November 1, 2025 10:55
@daFish
Copy link
Contributor Author

daFish commented Nov 1, 2025

@Kocal I took the chance to add playwright tests. I'll submit another PR with some changes to the documentation to enhance the DX.

@daFish daFish marked this pull request as ready for review November 1, 2025 11:02
Copy link
Member

@Kocal Kocal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Marcus, that's much appreciated!

I only have some comments about the E2E test, and of course any documentation improvement is welcomed :)

@carsonbot carsonbot added Status: Needs Work Additional work is needed and removed Status: Needs Review Needs to be reviewed labels Nov 2, 2025
@daFish daFish force-pushed the fix/autocomplete-tomselect-cleanup branch from 1a899ea to 2b36965 Compare November 3, 2025 06:46
@carsonbot carsonbot added Status: Needs Review Needs to be reviewed and removed Status: Needs Work Additional work is needed labels Nov 3, 2025
@daFish
Copy link
Contributor Author

daFish commented Nov 3, 2025

  • removed the browser test because I couldn't find a way to reproduce it here
  • added a simple non-ajax example for Autocomplete

@daFish
Copy link
Contributor Author

daFish commented Nov 3, 2025

Ok, this is weird. I have force-pushed my changes this morning and the PR is still not updated. My changes are still being processed. 🤨

@daFish daFish force-pushed the fix/autocomplete-tomselect-cleanup branch from 893194e to 025ed56 Compare November 3, 2025 11:28
@daFish
Copy link
Contributor Author

daFish commented Nov 3, 2025

Rebased against 2.x and force-pushed again. Works now.

@daFish
Copy link
Contributor Author

daFish commented Nov 8, 2025

@Kocal After several attempts trying to reproduce the behaviour locally, I was unable to provoce it. How shall we move forward?

Copy link
Member

@smnandre smnandre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of comments passing by, thank you for the PR!

@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
declare(strict_types=1);


class AutocompleteSelectType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public function buildForm(FormBuilderInterface $builder, array $options)
public function buildForm(FormBuilderInterface $builder, array $options): void

// clear the text input after selecting a value
onItemAdd: () => {
this.tomSelect.setTextboxValue('');
this.tomSelect?.setTextboxValue('');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not supposed to happen, is it ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can make it more defensive when something like this happens.

Comment on lines +176 to +178
if (!this.tomSelect) {
return;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same thing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

optgroupField: 'group_by',
// avoid extra filtering after results are returned
score: (search: string) => (item: any) => 1,
score: (_search: string) => (_item: any) => 1,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why this change ? genuine question here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The underscore is used to indicate an unused variable while making the linter happy.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was he unhappy ? never observed that .. but ok :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤷🏻‍♂️ It's not easy being a linter I guess.

Comment on lines +451 to +454
if (!this.tomSelect) {
return;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same ting, not supposed to happen here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will be reverted.

@daFish
Copy link
Contributor Author

daFish commented Nov 16, 2025

@smnandre The defensive checks can remain IHMO. We tell other developers that all code paths are safe. Yes, it should not happen but we make it explicit that it will not happen. Especially in the callbacks, e.g. onItemAdd or onOptionAdd. WDYT?

@daFish daFish force-pushed the fix/autocomplete-tomselect-cleanup branch from 025ed56 to f4bd90b Compare November 16, 2025 14:05
@daFish daFish force-pushed the fix/autocomplete-tomselect-cleanup branch from f4bd90b to 60f3a9d Compare November 16, 2025 14:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Autocomplete] Error: Tom Select already initialized on this element

4 participants