Select2选择器点击无响应问题排查及代码求助
我看了你的代码和返回的数据,问题出在后端返回的数据格式错误,加上前端解析和格式化逻辑的问题,导致Select2没法正确识别选项,所以点击选择器时没反应。咱们一步步来修复:
1. 先修正后端返回的数据格式
你现在后端返回的是一个包含JSON字符串的数组,而且部分元素末尾还有多余的逗号,这完全不符合Select2需要的结构。
你当前的返回数据(有问题):
["{"tradename" :"pascual","fiscalname" :"pascual sl","nif" :"4568424"},","{"tradename" :"Jacinto","fiscalname" :"Jacinto sl","nif" :"8764564"},","{"tradename" :"Calzapeques","fiscalname" :"Calzapeques sl","nif" :"4568753"}"]
正确的返回格式应该是这样的纯对象数组:
[ {"tradename": "pascual", "fiscalname": "pascual sl", "nif": "4568424"}, {"tradename": "Jacinto", "fiscalname": "Jacinto sl", "nif": "8764564"}, {"tradename": "Calzapeques", "fiscalname": "Calzapeques sl", "nif": "4568753"} ]
要去掉每个对象外面的引号,以及元素末尾多余的逗号,直接返回标准的JSON对象数组,同时确保后端响应的Content-Type是application/json。
2. 修正前端的processResults函数
原来你在processResults里做了JSON.parse(data),但如果后端返回正确的JSON,data已经是解析好的数组了,不需要再parse。而且我们需要给每个数据项添加上Select2默认需要的id和text属性(用来识别选项):
processResults: function (data, params) { params.page = params.page || 1; // 格式化数据,给每个项添加id和text,同时保留原属性 const formattedResults = data.map(item => ({ id: item.nif, // 用nif作为唯一标识 text: item.tradename, // 用商号作为默认显示文本 ...item // 保留tradename、fiscalname等所有原属性 })); return { results: formattedResults, pagination: { more: (params.page * 30) < data.length } }; },
3. 重写格式化函数formatRepo和formatRepoSelection
原来的formatRepo里用repo.split('"')是错误的,因为现在repo已经是一个对象,不是字符串了。我们直接访问对象的属性即可:
function formatRepo(repo) { if (repo.loading) { return repo.text; } // 直接渲染HTML,访问repo的属性 const markup = ` <div class="select2-result-repository clearfix" onClick="tradename('${repo.tradename}')"> <div class="select2-result-repository__avatar"><img src="" /></div> <div class="select2-result-repository__meta"> <div class="select2-result-repository__title"><strong>${repo.tradename}</strong></div> <div class="select2-result-repository__statistics"> <div class="select2-result-repository__forks">${repo.fiscalname}</div> <div class="select2-result-repository__stargazers">${repo.nif}</div> </div> </div> </div> `; return markup; } function formatRepoSelection(repo) { // 选择后在输入框显示的文本,这里用商号+税号 return `${repo.tradename} (${repo.nif})` || repo.text; }
4. 完整的修正后代码
把上面的修改整合到你的代码里,最终版本如下:
$(".js-data-example-ajax").select2({ ajax: { url: "{{ path("ajax_search_client") }}", dataType: 'json', delay: 250, data: function (params) { return { data: params.term, // search term page: params.page }; }, processResults: function (data, params) { params.page = params.page || 1; const formattedResults = data.map(item => ({ id: item.nif, text: item.tradename, ...item })); return { results: formattedResults, pagination: { more: (params.page * 30) < data.length } }; }, cache: true }, placeholder: 'Buscar un cliente', escapeMarkup: function (markup) { return markup; }, // 允许自定义HTML minimumInputLength: 1, templateResult: formatRepo, templateSelection: formatRepoSelection }); function formatRepo(repo) { if (repo.loading) { return repo.text; } const markup = ` <div class="select2-result-repository clearfix" onClick="tradename('${repo.tradename}')"> <div class="select2-result-repository__avatar"><img src="" /></div> <div class="select2-result-repository__meta"> <div class="select2-result-repository__title"><strong>${repo.tradename}</strong></div> <div class="select2-result-repository__statistics"> <div class="select2-result-repository__forks">${repo.fiscalname}</div> <div class="select2-result-repository__stargazers">${repo.nif}</div> </div> </div> </div> `; return markup; } function formatRepoSelection(repo) { return `${repo.tradename} (${repo.nif})` || repo.text; }
这样修改后,Select2应该就能正确加载数据,并且点击选项时正常工作了。
内容的提问来源于stack exchange,提问作者Eduardo

