Bold search text characters in jQuery Autocomplete dropdown? - javascript

If you enter "che" in https://jsfiddle.net/mgjftrdz/ (code from http://jqueryui.com/autocomplete/#multiple) it lists two items:
Cheese
Cream-cheese
What changes to that would I need to make those particular characters bold in the drop-down results like this?
Cheese
Cream-cheese
function split(val) {
return val.split(/,\s*/);
}
function extractLast(term) {
return split(term).pop();
}
$("#tags")
// don't navigate away from the field on tab when selecting an item
.bind("keydown", function(event) {
if (event.keyCode === $.ui.keyCode.TAB &&
$(this).autocomplete("instance").menu.active) {
event.preventDefault();
}
})
.autocomplete({
minLength: 0,
source: function(request, response) {
// delegate back to autocomplete, but extract the last term
response($.ui.autocomplete.filter(
availableTags, extractLast(request.term)));
},
focus: function() {
// prevent value inserted on focus
return false;
},
select: function(event, ui) {
var terms = split(this.value);
// remove the current input
terms.pop();
// add the selected item
terms.push(ui.item.value);
// add placeholder to get the comma-and-space at the end
terms.push("");
this.value = terms.join(", ");
return false;
}
});
});

You can try
$(function() {
var availableTags = [{
label: 'honey',
value: 1
}, {
label: 'apples',
value: 2
}, {
label: 'milk',
value: 3
}, {
label: 'tea',
value: 4
}, {
label: 'oranges',
value: 5
}, {
label: 'bread',
value: 6
}, {
label: 'cheese',
value: 7
}, {
label: 'apple-sauce',
value: 8
}, {
label: 'cream-cheese',
value: 9
}];
function split(val) {
return val.split(/,\s*/);
}
function extractLast(term) {
return split(term).pop();
}
$("#tags")
// don't navigate away from the field on tab when selecting an item
.bind("keydown", function(event) {
if (event.keyCode === $.ui.keyCode.TAB &&
$(this).autocomplete("instance").menu.active) {
event.preventDefault();
}
})
.autocomplete({
minLength: 0,
source: function(request, response) {
// delegate back to autocomplete, but extract the last term
var list = $.ui.autocomplete.filter(availableTags, extractLast(request.term));
if (request.term) {
var regex = new RegExp('(' + $.ui.autocomplete.escapeRegex(request.term) + ')', "gi");
list = list.map(function(item) {
return {
label: item.label.replace(regex, '<b>$1</b>'),
value: item.value
}
})
}
response(list);
},
focus: function() {
// prevent value inserted on focus
return false;
},
select: function(event, ui) {
var terms = split(this.value);
// remove the current input
terms.pop();
// add the selected item
terms.push(ui.item.value);
// add placeholder to get the comma-and-space at the end
terms.push("");
this.value = terms.join(", ");
return false;
}
});
$("#tags").data('uiAutocomplete')._renderItem = function(ul, item) {
return $("<li>").append(item.label).appendTo(ul);
};
});
<link rel="stylesheet" type="text/css" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script type="text/javascript" src="//code.jquery.com/jquery-1.10.2.js"></script>
<script type="text/javascript" src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<div>
<label for="tags">Snack foods:</label>
<input id="tags" size="50">
</div>

Just used a create option to prepare HTML that needs to be rendered.
Below is the piece of that code. Although I know that this is not optimized one but you can do that yourself. But I think this is what you require.
Here is working JSFiddle https://jsfiddle.net/mgjftrdz/2/
create: function () {
$(this).data('ui-autocomplete')._renderItem = function (ul, item) {
var startIndex = item.label.indexOf($("#tags" ).val())
var endIndex = startIndex + $("#tags" ).val().length;
var totalLength = $("#tags" ).val();
var arr = item.label.split('');
var newLabel="<label>";
for(var i=0 ; i < arr.length; i++){
newLabel+= (i>= startIndex && i <= endIndex) ? "<b>"+arr[i]+"</b>": arr[i];
}
newLabel += "</label>"
return $('<li>')
.append('<a>' + newLabel + '</a>')
.appendTo(ul);
};
},

Related

Typeahead and Bloodhound dynamically change local values

I am using Typeahead (with default suggestions) with Bloodhound and everything works fine so far. However, I have some problems when I try to dynamically change the values of the suggestions.
For example, I have an array of available suggestions like [ "A", "B", "C"] when I select one of those elements it is added to a combo box. But I want to ensure that each element is only selected once. That's why I want to remove the element from the list. So if a user chooses the element "B" the list of available suggestions should look like: ["A", "C"].
Here is the code that I try:
var available_items = [ "Item 1", "Item 2", ... , "Item N" ];
var my_bloodhound = new Bloodhound(
{
local: available_items,
queryTokenizer: Bloodhound.tokenizers.whitespace,
datumTokenizer: Bloodhound.tokenizers.whitespace
)};
$( "#my-typeahead-field" ).typeahead(
{
minLength: 0,
highlight: true
},
{
name: 'items',
limit: 10,
source: search_function,
});
var f = function( )
{
return available_categories.filter( element => !selected_items.includes( element ) );
}
function search_function( query, sync, async )
{
if( "" === query )
{
sync( f )
}
else
{
my_bloodhound.search( query, sync);
}
}
Please note that the array "selected_items" is filled when a user select an element of the suggestion list. I try many different approachs like this:
http://jsfiddle.net/likeuntomurphy/tvp9Q/
or the one where I use the typeahead:selected event:
$("#my-typeahead-field").bind('typeahead:select', function( event, item )
{
console.log('Selection: ' + item);
selected_items.push( item );
available_categories = available_categories.filter( element => !selected_items.includes( element ) );
});
But none of them works. Does anyone have an idea how to fix this problem?
It's a solution. You can refer it. Hope to help, my friend :))
var selected = [];
var available_items = [ "Item 1", "Item 2", "Item 3" ];
var select = function(e, datum, dataset) {
selected.push(datum);
$("#selected").text(JSON.stringify(selected));
$("input.typeahead").val("");
}
var filter = function(suggestions) {
return $.grep(suggestions, function(suggestion) {
return $.inArray(suggestion, selected) === -1;
});
}
var data = new Bloodhound({
name: 'animals',
local: available_items,
datumTokenizer: function(d) {
return Bloodhound.tokenizers.whitespace(d);
},
queryTokenizer: Bloodhound.tokenizers.whitespace
});
data.initialize();
$('input.typeahead').typeahead(null,
{
name: 'animals',
displayKey: function(item){
return item;
},
/* don't use
source: data.ttAdapter(), */
source: function(query, cb) {
data.get(query, function(suggestions) {
cb(filter(suggestions));
});
},
templates: {
empty: '<div class="empty-message">No matches.</div>'
}
}
).bind('typeahead:selected', select);
http://jsfiddle.net/mtLkns0e/

jQuery autocomplete suggests all options regardless of input entry

I have a jQuery script that will get a JSON response and create as many "player" objects as there are in the response.
It will then add to availablePlayers which I then use as the variable for the source: field of autocomplete
When a user selects a player name and clicks the "add" button it will, at the moment, just display the guid and name of a player.
However, no matter what letters I type, all the players are given as an option. To illustrate this, if I type "Z" and none of the players have Z in their name, they options are still displayed.
How can I refine this functionality?
HTML
<div class="player-widget">
<label for "players">Players</label>
<input id="player" />
<input id="playerGUID" hidden />
<button id="add">Add</button>
</div>
jQuery
$(document).ready(function(){
var availablePlayers = []; // BLANK ARRAY OF PLAYERS
$("#player").autocomplete({
source: availablePlayers,
response: function (event, ui) {
ui.content = $.map(ui.content, function(value, key) {
return {
label: value.name,
value: value.guid
}
});
},
focus: function(event, ui) {
$("#player").val(ui.item.label);
return false;
},
select: function (event, ui) {
$("#player").val(ui.item.label); // display the selected text
$("#playerGUID").val(ui.item.value); // save selected id to hidden input
return false;
}
});
$.getJSON("http://localhost/Websites/Player-Widgets/service.php", function(data) {
var feedHTML = '';
// LOOP THROUGH EACH PLAYER
$.each(data.players, function(i, player) {
// DEFINE VARIABLES - BASED ON PLAYER ATTRIBUTES
var guid = player.guid;
var name = player.name;
var dob = player.date_of_birth;
var birth = player.birthplace;
var height = player.height;
var weight = player.weight;
var position = player.position;
var honours = player.honours;
// CREATE NEW PLAYER (OBJECT)
var player = {
guid: guid,
name: name,
position: position
};
// ADD TO PLAYER TAG ARRAY
availablePlayers.push(player);
});
console.log("User friendly array");
$.each(availablePlayers, function(i, val) {
console.log(val.guid + " - " + val.name + " [" + val.position + "]");
});
console.log("Array printout");
console.log(JSON.stringify(availablePlayers));
}).done(function(){
console.log("Done! Success!");
$("#player").autocomplete("option", "source", availablePlayers);
});
$("#add").click(function() {
alert($("#playerGUID").val() + " - " + $("#player").val());
});
});
Sample JSON response
{
"players": [
{
"guid": "1",
"name": "Matias Aguero",
"date_of_birth": "1981-02-13",
"birthplace": "San Nicolas, Argentina",
"height": "1.83m (6' 0\")",
"weight": "109kg (17st 2lb)",
"position": "Prop",
"honours": "40 caps"
},
{
"guid": "2",
"name": "George Catchpole",
"date_of_birth": "1994-02-22",
"birthplace": "Norwich, England",
"height": "1.85em (6ft 1\")",
"weight": "104kg (16st 5lb)",
"position": "Centre",
"honours": ""
}
]
}
Your problem is in the source function.
Source function uses request to pass term param to query, and you are ignoring it.
If you're using availablePlayers to query, you should use
source: availablePlayers
and your current function to map {label, text} object in response parameter.
response: function (event, ui) {
ui.content = $.map(ui.content, function(value, key) {
return {
label: value.name,
value: value.guid
}
});
}

Kendo TreeView Search with Highlight

I have a KendoTreeview with spriteclass. I want to highlight the nodes (root as well as child nodes) with my search term. I have implemented the search functionality. But the issue when i search it is highlighting the term in the nodes but missing the SpriteClass in the nodes after first search. Any idea ?
jsFiddle code
$('#search-term').on('keyup', function () {
$('span.k-in > span.highlight').each(function () {
$(this).parent().text($(this).parent().text());
});
// ignore if no search term
if ($.trim($(this).val()) == '') {
return;
}
var term = this.value.toUpperCase();
var tlen = term.length;
$('#treeview-sprites span.k-in').each(function (index) {
var text = $(this).text();
var html = '';
var q = 0;
while ((p = text.toUpperCase().indexOf(term, q)) >= 0) {
html += text.substring(q, p) + '<span class="highlight">' + text.substr(p, tlen) + '</span>';
q = p + tlen;
}
if (q > 0) {
html += text.substring(q);
$(this).html(html);
$(this).parentsUntil('.k-treeview').filter('.k-item').each(
function (index, element) {
$('#treeview-sprites').data('kendoTreeView').expand($(this));
$(this).data('search-term', term);
});
}
});
$("#treeview-sprites").kendoTreeView({
dataSource: [{
text: "My Documents",
expanded: true,
spriteCssClass: "rootfolder",
items: [{
text: "Kendo UI Project",
expanded: true,
spriteCssClass: "folder",
items: [{
text: "about.html",
spriteCssClass: "html"
}, {
text: "index.html",
spriteCssClass: "html"
}, {
text: "logo.png",
spriteCssClass: "image"
}]
}, {
text: "New Web Site",
expanded: true,
spriteCssClass: "folder",
items: [{
text: "mockup.jpg",
spriteCssClass: "image"
}, {
text: "Research.pdf",
spriteCssClass: "pdf"
}, ]
}, {
text: "Reports",
expanded: true,
spriteCssClass: "folder",
items: [{
text: "February.pdf",
spriteCssClass: "pdf"
}, {
text: "March.pdf",
spriteCssClass: "pdf"
}, {
text: "April.pdf",
spriteCssClass: "pdf"
}]
}]
}]
})
;
Kendo's tree view widget doesn't like it if you muck around in its HTML, so I suggest modifying the data source instead (this will require the encoded option for all items in the DS).
In the keyup handler, you reset the DS whenever you search to clear highlighting, then instead of replacing the element's HTML directly, you set the model's text property:
$('#search-term').on('keyup', function () {
var treeView = $("#treeview-sprites").getKendoTreeView();
treeView.dataSource.data(pristine);
// ignore if no search term
if ($.trim($(this).val()) == '') {
return;
}
var term = this.value.toUpperCase();
var tlen = term.length;
$('#treeview-sprites span.k-in').each(function (index) {
var text = $(this).text();
var html = '';
var q = 0;
while ((p = text.toUpperCase().indexOf(term, q)) >= 0) {
html += text.substring(q, p) + '<span class="highlight">' + text.substr(p, tlen) + '</span>';
q = p + tlen;
}
if (q > 0) {
html += text.substring(q);
var dataItem = treeView.dataItem($(this));
dataItem.set("text", html);
$(this).parentsUntil('.k-treeview').filter('.k-item').each(
function (index, element) {
$('#treeview-sprites').data('kendoTreeView').expand($(this));
$(this).data('search-term', term);
});
}
});
$('#treeview-sprites .k-item').each(function () {
if ($(this).data('search-term') != term) {
$('#treeview-sprites').data('kendoTreeView').collapse($(this));
}
});
});
The tree definition needs the encoded option for this to work:
var pristine = [{
encoded: false,
text: "Kendo UI Project",
expanded: true,
spriteCssClass: "folder",
items: [{
encoded: false,
text: "about.html",
spriteCssClass: "html"
}, {
encoded: false,
text: "index.html",
spriteCssClass: "html"
}, {
encoded: false,
text: "logo.png",
spriteCssClass: "image"
}]
}, {
encoded: false,
text: "New Web Site",
expanded: true,
spriteCssClass: "folder",
items: [{
encoded: false,
text: "mockup.jpg",
spriteCssClass: "image"
}, {
encoded: false,
text: "Research.pdf",
spriteCssClass: "pdf"
}, ]
}, {
encoded: false,
text: "Reports",
expanded: true,
spriteCssClass: "folder",
items: [{
encoded: false,
text: "February.pdf",
spriteCssClass: "pdf"
}, {
encoded: false,
text: "March.pdf",
spriteCssClass: "pdf"
}, {
encoded: false,
text: "April.pdf",
spriteCssClass: "pdf"
}]
}];
$("#treeview-sprites").kendoTreeView({
dataSource: [{
text: "My Documents",
expanded: true,
spriteCssClass: "rootfolder",
items: pristine
}]
});
(demo)
Good job guys, just what I neeeded!
Using your code I did a small tweak (actually added just two lines of jquery filtering), so that now when searching for a keyword, the treeview shows only the branches that contain highlighted texts. Easy peasy! :)
Other branches are hidden if they do not contain the higlighted text. Simple as that.
This means we now have a VisualStudio-like treeview search (see the Visual Studio Solution Explorer Search and Filter: http://goo.gl/qr7yVb).
Here's my code and demo on jsfiddle: http://jsfiddle.net/ComboFusion/d0qespaz/2/
HTML:
<input id="treeViewSearchInput"></input>
<ul id="treeview">
<li data-expanded="true">My Web Site
<ul>
<li data-expanded="true">images
<ul>
<li>logo.png</li>
<li>body-back.png</li>
<li>my-photo.jpg</li>
</ul>
</li>
<li data-expanded="true">resources
<ul>
<li data-expanded="true">pdf
<ul>
<li>brochure.pdf</li>
<li>prices.pdf</li>
</ul>
</li>
<li>zip</li>
</ul>
</li>
<li>about.html</li>
<li>contacts.html</li>
<li>index.html</li>
<li>portfolio.html</li>
</ul>
</li>
<li>Another Root</li>
</ul>
CSS
span.k-in > span.highlight {
background: #7EA700;
color: #ffffff;
border: 1px solid green;
padding: 1px;
}
JAVASCRIPT
function InitSearch(treeViewId, searchInputId) {
var tv = $(treeViewId).data('kendoTreeView');
$(searchInputId).on('keyup', function () {
$(treeViewId + ' li.k-item').show();
$('span.k-in > span.highlight').each(function () {
$(this).parent().text($(this).parent().text());
});
// ignore if no search term
if ($.trim($(this).val()) === '') {
return;
}
var term = this.value.toUpperCase();
var tlen = term.length;
$(treeViewId + ' span.k-in').each(function (index) {
var text = $(this).text();
var html = '';
var q = 0;
var p;
while ((p = text.toUpperCase().indexOf(term, q)) >= 0) {
html += text.substring(q, p) + '<span class="highlight">' + text.substr(p, tlen) + '</span>';
q = p + tlen;
}
if (q > 0) {
html += text.substring(q);
$(this).html(html);
$(this).parentsUntil('.k-treeview').filter('.k-item').each(function (index, element) {
tv.expand($(this));
$(this).data('SearchTerm', term);
});
}
});
$(treeViewId + ' li.k-item:not(:has(".highlight"))').hide();
$(treeViewId + ' li.k-item').expand(".k-item");
});
}
var $tv = $("#treeview").kendoTreeView();
InitSearch("#treeview", "#treeViewSearchInput");
Another tweak from me :)
What I did was change the highlight code in order to preserve anything else that might exist in the node html (such as sprite span for example).
I also implemented it as a TypeScript class wrapper around the TreeView.
If you don't want TypeScript stuff just copy the code out and it should work fine :)
export class SearchableTreeView {
TreeView: kendo.ui.TreeView;
emphasisClass: string;
constructor(treeView: kendo.ui.TreeView) {
this.TreeView = treeView;
this.emphasisClass = "bg-warning";
}
search(term: string): void {
var treeElement: JQuery = this.TreeView.element;
var tv: kendo.ui.TreeView = this.TreeView;
var emphClass = this.emphasisClass;
this.resetHighlights();
// ignore if no search term
if ($.trim(term) === '') { return; }
var term = term.toUpperCase();
var tlen = term.length;
$('span.k-in', treeElement).each(function (index) {
// find all corresponding nodes
var node = $(this);
var htmlContent = node.html();
var text = node.text();
var searchPosition = text.toUpperCase().indexOf(term);
if (searchPosition === -1) {
// continue
return true;
}
var generatedHtml = '<span class="highlight-container">' + text.substr(0, searchPosition) + '<span class="' + emphClass + '">' + text.substr(searchPosition, tlen) + '</span>' + text.substr(searchPosition + tlen) + '</span>';
htmlContent = htmlContent.replace(text, generatedHtml);
node.html(htmlContent);
node.parentsUntil('.k-treeview').filter('.k-item').each(
function (index, element) {
tv.expand($(this));
$(this).data('search-term', term);
}
);
});
$('.k-item', treeElement).each(function () {
if ($(this).data('search-term') != term) {
tv.collapse($(this));
}
});
}
resetHighlights(): void {
this.TreeView.element.find("span.k-in:has('." + this.emphasisClass + "')")
.each(function () {
var node = $(this);
var text = node.text();
$(".highlight-container", node).remove();
node.append(text);
});
}
}
$("#textBox").on("input", function () {
var query = this.value.toLowerCase();
var dataSource = $("#Treeview").data("kendoTreeView").dataSource;
filter(dataSource, query);
});
function filter(dataSource, query) {
var uidData = [];
var data = dataSource instanceof kendo.data.DataSource && dataSource.data();
for (var i = 0; i < data.length; i++) {
var item = data[i];
var text = item.text.toLowerCase();
var isChecked = item.checked;
var itemVisible =
query === true
|| query === ""
|| text.indexOf(query) >= 0;
uidData.push({ UID: item.uid, Visible: itemVisible });
}
if (query != "") {
$.each(uidData, function (index, datavalue) {
if (datavalue.Visible) {
$("li[data-uid='" + datavalue.UID + "']").addClass("highlight");
}
else {
$("li[data-uid='" + datavalue.UID + "']").removeClass("highlight");
}
});
}
else {
$.each(uidData, function (index, datavalue) {
$("li[data-uid='" + datavalue.UID + "']").removeClass("highlight");
});
}
}
CSS :
.highlight {
background:#0fa1ba;
color:white;
}
For Angular 2+ you need to create a pipe for this feature.
import { Pipe, PipeTransform } from '#angular/core';
import { DomSanitizer } from '#angular/platform-browser';
import { NGXLogger } from 'ngx-logger';
#Pipe({
name: 'highlight'
})
export class TypeaheadHighlight implements PipeTransform {
constructor(private readonly _sanitizer: DomSanitizer, private readonly logger: NGXLogger) { }
transform(matchItem: any, query: any): string {
let matchedItem: any;
if (matchItem) {
matchedItem = matchItem.toString();
}
if (this.containsHtml(matchedItem)) {
this.logger.warn('Unsafe use of typeahead please use ngSanitize');
}
matchedItem = query ? ('' + matchedItem).replace(new RegExp(this.escapeRegexp(query), 'gi'), '<strong>$&</strong>') : matchedItem; // Replaces the capture string with a the same string inside of a "strong" tag
if (!this._sanitizer) {
matchedItem = this._sanitizer.bypassSecurityTrustHtml(matchedItem);
}
return matchedItem;
}
escapeRegexp = (queryToEscape) => queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
containsHtml = (matchItem) => /<.*>/g.test(matchItem);
}
Use of this pipe in html template....
<input name="searchTerm" type="text" [(ngModel)]="searchTerm" (keyup)='onkeyup(searchTerm)'
/>
</div>
<div style="height: 70vh;overflow: auto">
<kendo-treeview style="margin-top: 50px" id="availableColumns" [nodes]="availableColumns"
textField="displayName" kendoTreeViewExpandable kendoTreeViewFlatDataBinding idField="id"
parentIdField="parentId">
<ng-template kendoTreeViewNodeTemplate let-dataItem>
<span [tooltip]="dataItem.columnDescription"
[innerHtml]="dataItem.displayName | highlight:searchTerm "></span>
</ng-template>
</kendo-treeview>
</div>

Hide column in jQuery MultiColumn Autocomplete

I have a fine working jquery multicolumn autocomplete. Now i have to add a column which should be hidden. Basically its a ID of the values. So when the user selects the value i could able to get the ID of the selected row.
//Code:
<script type="text/javascript">
var autocompleteSource;
var colValues = [];
var columns = [{ name: 'Workflow Name', width: '200px' }, { name: 'Workflow Category', width: '150px' }, { name: 'Status', width: '100px' }, { name: 'Workflow Owner', width: '150px' }];
$.ajax({
url: "/Home/LoadWorkflowDropdown",
datatype: 'json',
mtype: 'GET',
success: OnComplete,
error: OnFail
});
function OnComplete(result) {
autocompleteSource = $.parseJSON(result)
$.each(autocompleteSource, function () {
colValues.push([this.WorkflowName, this.WorkflowCategory, this.StatusName, this.UserName]);
});
$.widget('custom.mcautocomplete', $.ui.autocomplete, {
_renderMenu: function (ul, items) {
var self = this,
thead;
if (this.options.showHeader) {
table = $('<div class="ui-widget-header" style="width:100%"></div>');
$.each(this.options.columns, function (index, item) {
table.append('<span style="padding:0 4px;float:left;width:' + item.width + ';">' + item.name + '</span>');
});
table.append('<div style="clear: both;"></div>');
ul.append(table);
}
$.each(items, function (index, item) {
self._renderItem(ul, item);
});
},
_renderItem: function (ul, item) {
var t = '',
result = '';
$.each(this.options.columns, function (index, column) {
t += '<span style="padding:0 4px;float:left;width:' + column.width + ';">' + item[column.valueField ? column.valueField : index] + '</span>'
});
result = $('<li></li>').data('item.autocomplete', item).append('<a class="mcacAnchor">' + t + '<div style="clear: both;"></div></a>').appendTo(ul);
return result;
}
});
$("#search").mcautocomplete({
showHeader: true,
columns: columns,
source: colValues,
select: function (event, ui) {
this.value = (ui.item ? ui.item[0] : '');
return false;
}
});
}
</script>
Working Fiddle here
Here i have modified js code to add unique id to each record and to get that value when user selects a particular option from the auto-suggest list. Fiddle
HTML: Create a hidden field to store the id of selected option
<input type="hidden" name="selectedId" id="selectedId" />
JS: Added ids in the array and retrieved those ids in select function by index value.
var columns = [{
name: 'Color',
width: '100px'},
{
name: 'Hex',
width: '70px'}],
colors = [['Red', '#f00', '1'], ['Green', '#0f0', '2'], ['Blue', '#00f', '3']];
$("#search").mcautocomplete({
showHeader: true,
columns: columns,
source: colors,
select: function(event, ui) {
$('#selectedId').val(ui.item[2]);
this.value = (ui.item ? ui.item[0] : '');
return false;
}
});

Select2 multiselect duplicates values

http://jsfiddle.net/tXFbk/2/
HTML:
<div class="control-group">
<label for="some_id" class="control-label">Some ID</label>
<div class="controls">
<input type="text" id="some_id" name="some_id" class="span4"/>
</div>
</div>
JS:
$(function() {
$('#some_id').select2({
allowClear: true,
placeholder: 'Some ID',
minimumInputLength: 2,
multiple: true,
data: [
{id: 1, text: 'some text'},
{id: 2, text: 'some other text'},
{id: 3, text: 'some more text'}
]
});
$('#some_id').select2('data', [
{'id':1,'text':'some text'}
]);
console.log($('#some_id').select2('val'));
});
On first load it duplicates values and after clearing value it doesn't clear it from input. Also if you add an item (eg. "some more text") and then remove it, it doesn't clear it from input value. Is there any way to make it stop duplicating values?
One more thing - how to disable adding already added items?
Select2 4.0.0 support duplicate tags.
Jsfiddle Demo link
$eventSelect.on("select2:select", function (e) {
log("select2:select", e);
$eventSelect.append('<option value="'+e.params.data.text+'">' +e.params.data.text + '</option>');
});
$eventSelect.on("select2:unselect", function (e) {
log("select2:unselect", e);
e.params.data.element.remove();
});
function formatResultData (data) {
if (!data.id) return data.text;
if (data.element.selected) return
return data.text;
};
Base on select2 event and github issues
Pic:
Check the following On Selecting event, and setting the isNew property in createSearchChoice
let me know if it resolved your issue
$('#some_id').select2({
tags: true,
tokenSeparators: [","],
createSearchChoice: function (term, data) {
if (term.trim().length > 0) {
if ($(data).filter(function () {
return this.text.toLowerCase().localeCompare(term.toLowerCase()) === 0;
}).length === 0) {
return {
id: term,
text: term,
isNew: true // this is necessary to check if the item is newly added or not
};
}
}
},
multiple: true,
minimumInputLength: 1,
allowClear: true,
data: [
{id: 1, text: 'some text'},
{id: 2, text: 'some other text'},
{id: 3, text: 'some more text'}
],
}).on("select2-selecting", function (e) {
var tagId = '';
if (e.choice.isNew) {
self.AddTagToDatabase(e.choice.text);
} else {
var isValidTag = true;
$(config.element[0] + ' ul li').find('div').each(function (index, item) {
if ($(item).html().toLowerCase().trim() == e.choice.text.toLowerCase().trim()) {
isValidTag = false;
e.choice.text = '';
return;
}
});
}
})
You need to trigger the change event of select2 to reflect the changes.
$("#dropdownId").val("yourValues").trigger("change");
after setting the values, you need to fire trigger values manually, to reflect the latest changes done in your dropdownlist

Categories