使用jquery select2插件时,如果已列出的ajax调用中存在有效值,如何防止选择新标记?

leo*_*ora 15 tags ajax jquery jquery-select2 jquery-select2-4

我正在使用带有多个选择的select2版本4,我支持用户添加新标签,但我想阻止人们选择新标签,如果该标签已存在于我的后端.

现在,如果用户输入已存在的标签并且我有标签:true,则它会在下拉列表中显示两个项目(现有的和新的项目).这是一个例子:

在此输入图像描述

正如你所看到的,"testTag2"是我后端的一个有效标签,所以它出现在选择中,但由于templateResult函数和标签: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]";
}
Run Code Online (Sandbox Code Playgroud)

}

Pro*_*eek 9

根据Select2 选项

更改搜索时选项的匹配方式当用户通过在搜索框中输入搜索词来过滤结果时,Select2使用内部"匹配器"将搜索词与搜索结果匹配.使用远程数据集时,Select2期望返回的结果已被过滤.

密钥匹配器值一个捕获搜索参数和数据对象的函数.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;
}
Run Code Online (Sandbox Code Playgroud)

我认为这是你的典型情况,除了你应该用("")替换("匹配"),并添加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;
}
Run Code Online (Sandbox Code Playgroud)


vij*_*ayP 5

如果我误解了你的问题,请纠正我。但根据我的理解,我提出了以下解决方案。

出于演示目的,我在框中预加载了几个<option>元素<select>,而不是使用简单的 JavaScript对象模仿响应ajax来提供数据。select2arrayajax

更新的小提琴链接: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> 
Run Code Online (Sandbox Code Playgroud)

在这里我们可以看到,<option>下拉列表中的最后一个存在有 text green

模仿响应的JSONdata对象ajax如下所示:

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' }
                ];
Run Code Online (Sandbox Code Playgroud)

此处再次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;
    }
Run Code Online (Sandbox Code Playgroud)

var uniqueTexts是一个数组,用于保存要显示给最终用户的唯一文本。在启动时,我们将其设置为null。因此,每当用户将注意力集中在选择框或输入搜索关键字时;matcher:每个选项都会调用回调。我们检查每个选项,看看它是否已经存在uniqueTexts[]。如果它是第一次出现,那么我们允许它显示;否则我们会返回null以避免它第二次显示。

我还添加了一个escapeMarkup:回调处理程序,每当向最终用户显示选项时就会调用该处理程序。此时我们可以再次设置uniqueTextsnull。这就是完整的一轮循环。用户再次可以聚焦或键入选择框。

function tagFormatResult(tag)工作原理如下:

1) 首先检查当前标签是否已被选择。如果已选择,则不要添加“[NEW]”文本tag.text

2) 其次,它检查 current 是否tag.text以文本形式出现select option多次。如果它出现在多个地方,那么也不要将“[NEW]”添加到tag.text.

3) 在所有其他情况下,请继续将“[NEW]”添加到tag.text.

我希望这会对你有所帮助。 更新链接: https: //jsfiddle.net/vijayP/akyzt9Ld/11/