How to prevent duplicate with Bootstrap Tokenfield When using Jquery Ui Autocomplete

烂漫一生 提交于 2019-12-03 03:08:13

I think you've done it all, all you are left to do is to replace the class

So after the first code, instead of the second code write

$('.tokenfield').on('tokenfield:createtoken', function (event) {
    var existingTokens = $(this).tokenfield('getTokens');
    $.each(existingTokens, function(index, token) {
        if (token.value === event.attrs.value)
            event.preventDefault();
    });
});

The difference here is your class that has to be applied and it works both for Twitter Typeahead and Jquery Ui

This prevents listing items that have already been added as tokens:

    $('.tokenfield').on('tokenfield:createdtoken tokenfield:removedtoken', function (event) {
    var field = $(this);
    var currentTokens = field.tokenfield('getTokens');
    var originalSource = field.data('bs.tokenfield').options.autocomplete.source;
    var newSource = originalSource.slice(); //clone original autocomplete source
    for (var i = newSource.length - 1; i >= 0; i--) {
      for (var j = currentTokens.length - 1; j >= 0; j--) {
        if (JSON.stringify(currentTokens[j].label) == JSON.stringify(newSource[i]) 
          || JSON.stringify(currentTokens[j]) == JSON.stringify(newSource[i]) ) {
          //remove the token from the newSource
          var index = newSource.indexOf(newSource[i]);
          if (index > -1) 
            newSource.splice(index, 1);
        };
      };
    };
    //update source
    field.data('bs.tokenfield').$input.autocomplete({source: newSource})
})

This function is called after token is created or deleted to update the list. It uses JSON.stringify() to compare objects, and does the comparison for string objects and for {value: "foo", label: "bar"} source objects.

@Javier Your solution work good but sometimes it gets buggy and add twice the token! Have you got idea for this behaviour?

PS After seen the documentation i found the solution. Both event handling are needed. Because events are fired before and after creation/edit/remove of tokens.

So you need this to prevent the add (before create event)

$('#tokenfield').on('tokenfield:createtoken', function (event) {
    var existingTokens = $(this).tokenfield('getTokens');
    //check the capitalized version
    event.attrs.value =  capitalizeFirstLetter(event.attrs.value);
    $.each(existingTokens, function(index, token) {
        if (token.value === event.attrs.value) {
            event.preventDefault();
            return false;
        }
    });
});

And this other too, as you suggested, for the source-list (after create event)

$('#tokenfield').on('tokenfield:createdtoken tokenfield:removedtoken', function (event) {
    var field = $(this);
    var currentTokens = field.tokenfield('getTokens').map(function(i){return i.value});
    var originalSource = field.data('bs.tokenfield').options.autocomplete.source;
    var newSource = [];
    for (var i = 0; i<originalSource.length; i++) {
      if(currentTokens.indexOf(originalSource[i])==-1){
        newSource.push(originalSource[i]);
      }
    };
    //update source
    field.data('bs.tokenfield').$input.autocomplete({source: newSource});
    //empty the input field
    $(".tokenfield.form-control").find("input.token-input").val("");
});

NOTE: I changed the "check loop", (double for was overkilling), and added a check to avoid "capitalized" matching, just in case you need it.

function capitalizeFirstLetter(string) {
    return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
}
$('.tokenfield').on('tokenfield:createtoken', function (event) {
    var existingTokens = $(this).tokenfield('getTokens');
    $.each(existingTokens, function(index, token) {
        if (token.value === event.attrs.value)
            event.preventDefault();
    });
});
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!