使用 Stimulus Controller Ruby on Rails 消除 Slim 选择搜索事件

问题描述 投票:0回答:1

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('');
        }
      }
}

第一次打开搜索时,它给我:

enter image description here

也在 afterOpen 中尝试过 debounce(this.slimSelect.search(''), 300) 但仍然是同样的问题

ruby-on-rails debouncing stimulus-rails slimselect
1个回答
0
投票

这是我在所有 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 %>
© www.soinside.com 2019 - 2024. All rights reserved.