I have some forms in my app that are loaded via turbo_stream. The user select a category and, accordingly to the option, a form is generated, updating a turbo_frame. I’m trying to use select2 in the forms. Everything works fine when the page is loaded (select2 class outsite the frame), but I can’t make it work when the DOM changes. Any ideas?
My select2 file:
import $ from “jquery”;
import “select2”;
At first, I got the select2 function to be called at each turbo stream with:
document.addEventListener(“turbo:submit-end”, function() {
initSelect2();
});
But jQuery wasn’t able to get the requested class.
So, I got things working by using select2 (and jquery) inside a stimulus controller.
if is usefull ths is a stimulus controller for slim-select and work fine in a turbo frame:
import { Controller } from "stimulus"
import SlimSelect from 'slim-select'
export default class extends Controller {
static targets = [ 'simple', 'user', 'editor' ]
connect() {
if (this.hasSimpleTarget) {this.simpleTargets.forEach(element => this.simple(element))}
if (this.hasUserTarget) {this.userTargets.forEach(element => this.user(element))}
if (this.hasEditorTarget) {this.editorTargets.forEach(element => this.editor(element))}
}
simple(element) {
new SlimSelect({ select: element })
}
user(element) {
this.ajax(element, '/editor/users/list.json?')
}
editor(element) {
this.ajax(element, '/admin/users/list?filter[editor]=1&')
}
ajax(element, url) {
const slim = new SlimSelect({
select: element,
placeholder: 'Seleziona un utente',
searchingText: 'Sto cercando...',
searchPlaceholder: 'Digita per ricercare',
searchText: 'Nessun risultato',
allowDeselect: true,
ajax: function (search, callback) {
// Check search value. If you dont like it callback(false) or callback('Message String')
if (search.length < 3) {
callback('Inserire almeno 3 caratteri')
return
}
// Perform your own ajax request here
fetch(`${url}filter[text]=${search}`)
.then(function (response) { return response.json() })
.then(function (json) {
let data = []
for (let i = 0; i < json.users.length; i++) {
data.push({text: json.users[i].username, value: json.users[i].id})
}
// Upon successful fetch send data to callback function.
// Be sure to send data back in the proper format.
// Refer to the method setData for examples of proper format.
callback(data)
})
.catch(function(error) { callback(false) })
}
})
}
}
you can apply the same logic to Select2 and it should work fine