slim-select 问题论坛:https://github.com/brianvoe/slim-select/discussions/541
嗨,我正在使用 Ruby on Rails 和 Stimulus JS,并且过去 6 个月一直在我的项目中使用 slim select。我的团队接到了本季度更新绩效的任务。因此,作为一部分,我们通过 slimselect 通过 ajax 移动搜索部分,并且它正在工作。我现在唯一关注的是具有去抖搜索功能,这样我们就不会在每次按键时都访问服务器。如果有人能帮助我实现这一目标,那就太好了。
import { Controller } from "@hotwired/stimulus"
import SlimSelect from 'slim-select'
import debounce from "debounce";
import { authToken } from '../global'
export default class extends Controller {
connect() {
this.initializeInstance();
}
disconnect() {
this.slimSelect.destroy();
}
initializeInstance() {
this.searchIt = this.searchIt.bind(this);
const options = {
select: this.element,
settings: {
hideSelectedOption: true,
placeholderText: this.placeholder,
allowDeselect: true,
maxValuesShown: 100,
}
}
if (this.optionsUrl) {
options.settings.searchingText = 'Searching...'
options.events = {
search: this.searchIt,
afterOpen: () => {
this.slimSelect.search('');
}
}
}
this.slimSelect = new SlimSelect(options)
// Auto-populate the select with data from the prepopulateUrl
// This comes in handy for applying filters to the select
if (this.prepopulateUrl) {
fetch(this.prepopulateUrl, {
method: 'GET',
headers: {
'Accept': 'application/json',
'X-CSRF-Token': authToken(),
},
})
.then(response => response.json())
.then(data => {
const fieldMappings = this.fieldMappings;
const options = data.map(item => ({ text: item[fieldMappings.text], value: item[fieldMappings.value] }));
const selectedValues = data.map(item => item[fieldMappings.value]);
this.slimSelect.setData(options);
this.slimSelect.setSelected(selectedValues);
})
.catch(error => {
console.error('Error:', error);
});
}
}
reinitializeInstance() {
this.disconnect();
this.initializeInstance();
}
get optionsUrl () {
return this.element.dataset.optionsUrl
}
get placeholder () {
return this.element.getAttribute('placeholder')
}
get fieldMappings() {
return JSON.parse(this.element.dataset.fieldsMapping)
}
get prepopulateUrl() {
return this.element.dataset.prepopulateUrl
}
searchIt (search, currentData) {
return new Promise((resolve, reject) => {
const url = this.optionsUrl.replace('${search}', search);
fetch(url, {
method: 'GET',
headers: {
'Accept': 'application/json',
'X-CSRF-Token': authToken(),
},
})
.then((response) => response.json())
.then(data => {
const fieldMappings = this.fieldMappings;
// Take the data and create an array of options
// excluding any that are already selected in currentData
const options = data.filter((obj) => {
return !currentData.some((optionData) => {
return optionData.value === obj[fieldMappings.value]
})
})
.map((item) => {
return {
text: item[fieldMappings.text],
value: item[fieldMappings.value],
}
})
resolve([...options, ...currentData]);
})
});
}
}
我已经尝试过类似的方法来实现,当我在搜索中输入某些内容时它会起作用,除了第一次打开搜索时。
if (this.optionsUrl) {
options.settings.searchingText = 'Searching...'
options.events = {
search: debounce(this.searchIt, 300),
afterOpen: () => {
this.slimSelect.search('');
}
}
}
第一次打开搜索时,它给我:
也在 afterOpen 中尝试过 debounce(this.slimSelect.search(''), 300) 但仍然是同样的问题
这是我在所有 ROR 搜索表单中使用的去抖函数:
import { Controller } from "@hotwired/stimulus";
import debounce from "debounce";
export default class extends Controller {
initialize() {
this.submit = debounce(this.submit.bind(this), 300);
}
submit() {
this.element.requestSubmit();
}
}
之后在你的html中你需要做:
<%= form_with url: '/events', method: :get, data: { turbo_frame: "events", turbo_action: "advance", controller: "form", action: "input->form#submit" } do %>
...
<% end %>
<%= turbo_frame_tag "events" do %>
<section>
<%= render @events %>
</section>
<% end %>