You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails中Tom-select编辑表单如何保留选中值?

问题:Tom-select编辑表单时无法显示已保存的选中值

我用Tom-select实现的AJAX搜索功能正常,但编辑表单时,该字段无法显示已保存的位置选中值。设置默认值后也没效果,始终显示默认占位文本,请问怎么在编辑时保留已保存的值?


选择字段代码

<%= form.select field.name,   [], {}, placeholder: 'Type to search', data: {controller: 'ts--search', ts__search_url_value: autocomplete_srs_path, ts__search_selected_value: @selected_for_tomselect.to_json }, :required => field.required %>

Stimulus控制器代码

import { Controller } from "@hotwired/stimulus"
import { get }        from '@rails/request.js'
import TomSelect      from "tom-select"

export default class extends Controller {
  static values = { url: String, selected: String }

  connect() {
    this.element.setAttribute( "autocomplete", "off" );
  
    if (this.selectedValue == 'null') {
      var selected_json_data   = new Array();
      var selected_items_array = new Array();
    } else {
      var selected_json_data = JSON.parse(this.selectedValue)
      var selected_items_array = new Array();
      for(let i = 0; i < selected_json_data.length; i++) {
        selected_items_array.push(selected_json_data[i].id)
      }
    }
    
    var config = {
      plugins: ['clear_button', 'remove_button'],
      shouldLoad:function(q){
        return q.length > 2;
      },
      render: {
        option: this.render_option,
        item: this.render_option

      },
      loadThrottle: 300,
      valueField: 'id',
      options: selected_json_data,
      items: selected_items_array,
      sortField: {
        field: "description",
        direction: "asc"
      },
  
      load: (q, callback) => this.search(q, callback),
      
      
    }
  
    let this_tom_select = new TomSelect(this.element, config)
    this_tom_select.clearCache()
    
  }


  async search(q, callback) {
    const response = await get(this.urlValue, {
      query: { q: q },
      responseKind: 'json'
    })

    if(response.ok) {
      callback(await response.json)
    } else {
      callback()
    }
  }


  render_option(data, escape) {

    if(data.description)
      return `
      <div>
          ${escape(data.description)}</div>
      </div>`
    else
      return `<div>${escape(data.text)}</div>`
  }

}

Rails控制器Edit方法代码

@selected = get_location(@sr.properties.as_json['location']).description
@selected_for_tomselect = @selected

Autocomplete方法代码

def autocomplete
  list = Location.order(:description).where("description like :q", q: "%#{params[:q]}%")
  render(json: list.map do |u| { text: u.description, value: u.id } end)
end

解决方案

1. 修正后端传递的选中数据格式

当前@selected_for_tomselect只传递了字符串类型的描述,但Tom-select需要包含id和description(或text)的对象数组,和autocomplete接口返回的格式一致。

修改Edit方法:

location = get_location(@sr.properties.as_json['location'])
@selected_for_tomselect = [{ id: location.id, description: location.description }]

2. 调整Stimulus控制器的选中值处理逻辑

确保selectedValue解析后是正确的对象数组,同时兼容空值或格式错误的情况:

connect() {
  this.element.setAttribute("autocomplete", "off");

  let selected_json_data = [];
  let selected_items_array = [];

  if (this.selectedValue && this.selectedValue !== 'null') {
    try {
      selected_json_data = JSON.parse(this.selectedValue);
      // 统一转为数组格式
      if (!Array.isArray(selected_json_data)) {
        selected_json_data = [selected_json_data];
      }
      selected_items_array = selected_json_data.map(item => item.id);
    } catch (e) {
      console.error('解析选中值失败:', e);
    }
  }

  // 后续config配置保持不变...
}

3. 确保字段匹配一致性

检查Tom-select配置与数据格式的匹配:

  • valueField: 'id'要求每个选项必须包含id属性
  • 渲染函数使用data.description,因此选中数据里必须包含该字段,和autocomplete接口返回的字段对齐

4. 可选:初始化后手动补全选中项

如果上述调整后仍有问题,可以在Tom-select实例创建后手动添加选中项:

let this_tom_select = new TomSelect(this.element, config);
// 手动添加选中项(兼容config未生效的情况)
selected_items_array.forEach(id => {
  const option = selected_json_data.find(item => item.id === id);
  if (option) {
    this_tom_select.addOption(option);
    this_tom_select.addItem(id);
  }
});
this_tom_select.clearCache();

内容的提问来源于stack exchange,提问作者spacerobot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 20:11:47