使用 jquery select2 插件时,如果已列出 ajax 调用中的有效值,如何防止选择新标签?
Posted
技术标签:
【中文标题】使用 jquery select2 插件时,如果已列出 ajax 调用中的有效值,如何防止选择新标签?【英文标题】:When using jquery select2 plugin, how can I prevent new tags from being chosen if there is a valid value from the ajax call already listed? 【发布时间】:2015-12-30 19:06:24 【问题描述】:我正在使用带有多项选择的select2 version 4,我支持用户添加新标签,但如果我的后端已经存在该标签,我想阻止人们选择新标签。
现在如果用户输入一个已经存在的标签并且我有 tags:true 那么它会在下拉列表中显示两个项目(现有的和新的)。这是一个例子:
如您所见,“testTag2”是来自我的后端的有效标签,因此它显示在选择中,但由于 templateResult 功能和 tags:true 它还显示为第二项(让用户认为他们可以选择它作为新标签)。
如果下拉列表中没有作为另一个选项列出该文本,是否只在下拉列表中显示“NEW”标签选项?
这是我的 javascript 代码:
function SetupAppTags()
$("#Tags").select2(
theme: "classic",
width: "98%",
tags: true,
ajax:
url: "/Tag/Search",
dataType: 'json',
delay: 300,
data: function(params)
return q: params.term ;
,
processResults: function(data, params)
return results: data ;
,
cache: false
,
escapeMarkup: function(markup) return markup; ,
minimumInputLength: 3,
templateResult: tagFormatResult,
templateSelection: tagSelectionResult
);
function tagFormatResult(tag)
if (tag.loading)
return "Loading . . . <img src='/Content/Images/ajax-loader.gif' />";
else
if (tag.name)
var existsAlready = $("#Tags option[value='" + tag.id + "']").length > 0;
if (existsAlready)
return null;
return tag.name;
var length = $('#tagsContainer .select2-selection__choice').filter(function ()
return $(this).attr("title").toUpperCase() === person.text.toUpperCase();
).length;
if (length == 1)
return null;
return tag.text + " [NEW]";
【问题讨论】:
你可以为此创建一个小提琴吗?如果无法使用 Ajax,那么即使是简单的数据数组也足够了。 【参考方案1】:根据Select2 Options
更改搜索时选项的匹配方式当用户向下过滤时 通过在搜索框中输入搜索词得到结果,Select2 使用 一个内部“匹配器”,用于将搜索词与结果匹配。当一个遥控器 使用数据集,Select2 期望返回的结果有 已被过滤。
Key matcher Value 获取搜索参数和数据对象的函数。 Select2 将传递已传递的单个数据对象 从数据适配器返回到匹配器分别确定 如果它们应该显示。只有第一级对象将 传入,所以如果你正在处理嵌套数据,你需要匹配 那些单独的。
matcher: function (params, data)
// If there are no search terms, return all of the data
if ($.trim(params.term) === '')
return data;
// `params.term` should be the term that is used for searching
// `data.text` is the text that is displayed for the data object
if (data.text.indexOf(params.term) > -1)
var modifiedData = $.extend(, data, true);
modifiedData.text += ' (matched)';
// You can return modified objects from here
// This includes matching the `children` how you want in nested data sets
return modifiedData;
// Return `null` if the term should not be displayed
return null;
我认为这是您的典型案例,除了您应该将 ("matched") 替换为 ("") ,并添加 else 以在您的案例中添加“[NEW]”。
ajax 调用返回的数据应该是匹配器的输入。
因此您的代码应如下所示:
matcher: function (params, data)
// If there are no search terms, return all of the data
if ($.trim(params.term) === '')
return data;
// `params.term` should be the term that is used for searching
// `data.text` is the text that is displayed for the data object
if (data.text.indexOf(params.term) > -1)
var modifiedData = $.extend(, data, true);
//match was found then just show it.
// modifiedData.text += ' (matched)';
// You can return modified objects from here
// This includes matching the `children` how you want in nested data sets
return modifiedData;
else
//there is not match found , suggest adding NEW Tag.
modifiedData.text += '[NEW]';
return modifiedData;
// Return `null` if the term should not be displayed
return null;
【讨论】:
【参考方案2】:如果我误解了您的问题,请纠正我。但据我了解,我想出了以下解决方案。
出于演示目的,我在<select>
框中预加载了几个<option>
元素,而不是ajax
数据馈送到select2
我使用的是普通的JavaScript array
对象模仿ajax
响应。
更新的小提琴链接:https://jsfiddle.net/vijayP/akyzt9Ld/11/
html如下:
<div id="tagsContainer">
<select id="Tags" multiple="" name="Tags">
<option value="white">white</option>
<option value="green">green</option>
</select>
</div>
在这里我们可以看到,下拉列表中的最后一个<option>
包含文本green
。
模仿 ajax
响应的 JSON data
对象如下所示:
var data = [ id: 0, name:'yellow', text: 'yellow' ,
id: 1, name:'green', text: 'green' ,
id: 2, name:'cyan', text: 'cyan' ,
id: 3, name:'violet', text: 'violet' ,
id: 4, name:'gray', text: 'gray'
];
green
再次位于第 2 位。
select2
初始化和支持 JavaScript 代码如下:
var uniqueTexts = null; //array for holding unique text
$("#Tags").select2(
tags: true,
data: data,
templateResult: tagFormatResult,
escapeMarkup: function (markup)
uniqueTexts = null;
return markup;
,
matcher: function (params, data)
if(!uniqueTexts)
uniqueTexts = [];
var modifiedData = null;
if ($.trim(params.term) === '' || data.text.indexOf(params.term) > -1)
if(uniqueTexts.indexOf(data.text) == -1)
modifiedData = data;
uniqueTexts.push(modifiedData.text);
if(modifiedData)
return modifiedData;
return null;
);
function tagFormatResult(tag)
if (tag.loading)
return "Loading . . . <img src='/Content/Images/ajax-loader.gif' />";
else
var length = $('#tagsContainer .select2-selection__choice').filter(function ()
return $(this).attr("title").toUpperCase() === tag.text.toUpperCase();
).length;
if (length == 1)
return tag.text;
if (tag.text)
if(getOptionCount(tag.text) >1)
return tag.text;
else
return tag.text + " [NEW]";
return tag.text + " [NEW]";
function getOptionCount(tagText)
var count = 0;
var selectBoxOptions = $("#Tags option");
$(selectBoxOptions).each(function()
if(tagText == $(this).text())
count++;//increment the counter if option text is matching with tag text
);
return count;
var uniqueTexts
是一个数组,用于保存要显示给最终用户的唯一文本。在启动时,我们将其设置为null
。所以这个想法是每当用户关注选择框或输入搜索关键字时;为每个选项调用matcher:
回调。我们检查每个选项,看看它是否已经存在于uniqueTexts[]
中。如果它是第一次出现,那么我们允许它显示;否则我们返回null
以避免它第二次显示。
我还添加了一个escapeMarkup:
回调处理程序,只要向最终用户显示选项,就会调用它。这时我们可以再次将uniqueTexts
设置为null
。这是完整的一轮循环。用户可以再次聚焦或输入选择框。
function tagFormatResult(tag)
的工作原理如下:
1) 首先检查当前标签是否已经被选中。如果它已被选中,则不要将 "[NEW]" 文本添加到 tag.text
2) 其次,它检查当前tag.text
是否多次以select option
文本出现。如果它出现在多个地方,那么也不要将 "[NEW]" 添加到tag.text
。
3) 在所有其他情况下,将 "[NEW]" 添加到 tag.text
。
我希望这会对你有所帮助。 更新链接:https://jsfiddle.net/vijayP/akyzt9Ld/11/
【讨论】:
如果我输入标签“绿色”,然后再次输入绿色,我会在下拉列表中看到两个选项都显示“绿色”。这似乎没有回答这个问题。我的目标是只显示一个项目并且在下拉列表中没有重复项 @leora,我会在下周检查它。 @leora。更新了答案。请看一下。以上是关于使用 jquery select2 插件时,如果已列出 ajax 调用中的有效值,如何防止选择新标签?的主要内容,如果未能解决你的问题,请参考以下文章