jQuery Autocomplete _renderItem if语句无法返回值 重复选择项过滤报错
问题修复方案
核心错误原因
_renderItem函数要求必须返回渲染完成的<li>元素的jQuery对象,你在判断到已存在已选项时直接返回了数字ID,导致Autocomplete内部调用返回结果的.data()方法时报类型错误。- 你在渲染当前候选项的过程中,就去查找还没插入到页面的
.rendered-feature-item元素,属于逻辑顺序错误,样式设置不会生效。 - 删除按钮重复绑定事件,每次选中新项都会给所有已存在的删除按钮重复绑定点击事件,会触发多次执行。
完整修正代码
jQuery("#feature-search-input").autocomplete({ appendTo: "#feature-searchbar", source: function (req, res) { jQuery.ajax({ url: myAPI, data: { term: req.term // 直接用回调传的req参数,不用重复取input值 }, type: "GET", dataType: 'json', crossOrigin: true, success: function (data) { // 先过滤掉已经选中的项,不需要再显示 const selectedIds = jQuery('#feature-results .feature-list-item').map(function(){ return jQuery(this).data('id') }).get() // 过滤已选+截断最多5条 let items = data.filter(item => !selectedIds.includes(item.id)).slice(0,5) const search_term = req.term items.push({ label: `<?php _e('More search results for'); ?> "${ search_term }"`, value: search_term, more_results: true }); res(items); } }); }, select: function(event, ui) { // 跳过更多结果项的选中逻辑 if(ui.item.more_results) { // 这里可以加跳转更多搜索结果的逻辑,没有就直接return jQuery(this).val('') return false } // 双重校验,已经选过的直接跳过 if(jQuery(`#feature-results .feature-list-item[data-id="${ui.item.id}"]`).length) { jQuery(this).val('') return false } const featureListItem = `<div class="feature-list-item" data-id="${ui.item.id}"> <input type='hidden' name='content-feature-ids[]' value='${ui.item.id}'> <p>${ ui.item.short_desc }</p> <a class='content-feature-remove'>Remove<a/> </div>`; jQuery('#feature-results').append(featureListItem); jQuery(this).val(''); return false } }).data("ui-autocomplete")._renderItem = function( ul, item ) { let item_label = '' // 特殊项处理:更多结果/无结果 if (item.more_results) { item_label = `<div class='rendered-feature-item'><p>${item.label}</p></div>` } else if (item.id && item.short_desc) { // 这里判断是否已选,你要是不想过滤想显示标红就取消source里的过滤,在这里加样式 const isSelected = jQuery(`#feature-results .feature-list-item[data-id="${item.id}"]`).length > 0 item_label = ` <div class='rendered-feature-item ${isSelected ? 'selected-feature' : ''}' data-id="${item.id}"> <p>${ item.short_desc }</p> </div> `; } else { item_label = `<strong>No Results</strong>`; } return jQuery( '<li>' ) .attr( "data-value", item.id ) .append( item_label ) .appendTo( ul ); }; // 删除按钮用事件委托,只绑定一次就够 jQuery('#feature-results').on('click', '.content-feature-remove', function(){ jQuery(this).parent().remove() })
可选配置
如果不需要过滤已选项,仅希望显示时标红提示且禁止选中,可以删掉source回调里的过滤逻辑,同时在select回调里保留已选判断返回false即可,额外加CSS控制已选样式:
.selected-feature { color: #999; pointer-events: none; }
内容的提问来源于stack exchange,提问作者SmoothOperator
相关产品推荐
相关产品推荐

