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
相关产品推荐
相关产品推荐

