Select2 multiselect duplicates values - javascript

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

Related

Binding array of object to Kendo grid popup multiselect

I'm trying to bind an array of id-value pairs to a kendo grid popup editor.
Got everything to work for creating a new record. Popup editor loads the custom editor and successfully submits the data to the controller.
The problem is when I try to edit records. The records displays properly in the row, but when I try to edit it, the multiselect does not hold the values.
Grid Markup
$("#ProjectSites-SubContract-grid").kendoGrid({
dataSource: {
type: "json",
schema: {
data: "Data",
total: "Total",
errors: "Errors",
model: {
id: "Id",
fields: {
DateOfContract: { type: 'date', editable: true },
DateOfCompletion: { type: 'date', editable: true },
AmountOfContract: { type: 'number', editable: true },
Contractor: { defaultValue: { id: "", name: "" } }
}
}
},
},
columns: [
{
field: "ScopeOfWork",
title: "Scope of Work",
template: "#=parseScopeOfWork(ScopeOfWork)#",
editor: scopeOfWorkEditor
},
]
});
});
Scope of Work editor
function scopeOfWorkEditor(container, options) {
$('<input data-text-field="name" data-value-field="id" data-bind="value:ScopeOfWork"/>')
.appendTo(container)
.kendoMultiSelect({
dataSource: {
data: [
#foreach (var scopeOfWork in Model.AvailableScopeOfWork)
{
<text>{ id : "#scopeOfWork.Value", name : "#scopeOfWork.Text" },</text>
},
]
}
});
parseScopeOfWork -
this method guys iterates through the object list and concats the name.
function parseScopeOfWork(scopeOfWork) {
var result = "";
for (var i = 0; i < scopeOfWork.length; i++) {
result += scopeOfWork[i].Name;
if (i < scopeOfWork.length - 1)
{
result += ", <br/>";
}
}
return result;
}
Here's a screenshot:
You're binding the SpaceOfWork to the new widget, but how that widget knows your Model ? I mean, just using data-bind doens't binds the model to the widget, it can't figure that by itself. I have two suggestions:
Set the value in the widget's initialization:
.kendoMultiSelect({
value: options.model.ScopeOfWork
Demo
Bind the model to the widget for good:
let $multiSelect = $('<input data-text-field="name" data-value-field="id" data-bind="value:ScopeOfWork"/>');
kendo.bind($multiSelect, options.model);
$multiSelect
.appendTo(container)
.kendoMultiSelect({ ...
Demo
Note: Edit the category cell in both demos to see the changes.

Validation of drop down having dynamic multiple drop down

Question is to :
Two drop downs should not be able to select same option.
Dynamically multiple drop downs are created. Since its dynamically id can't be used to with my jquery validation.
So, I tried doing my validation using class.
But I can not able to write correct validation jquery code for it.
Please help me.
use javascript set. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
run snippet below pick the same value in both drop downs and hit submit you will receive validation error
$(document).ready(function() {
var arr = [{
val: 1,
text: 'One'
}, {
val: 2,
text: 'Two'
}, {
val: 3,
text: 'Three'
}, {
val: 4,
text: 'Four'
}, {
val: 5,
text: 'Five'
}, {
val: 6,
text: 'Six'
}];
var sel = $('<select>').appendTo('#container');
var sel2 = $('<select>').appendTo('#container');
$(arr).each(function() {
sel.append($("<option>").attr('value', this.val).text(this.text));
sel2.append($("<option>").attr('value', this.val).text(this.text));
});
$('select').change(function(event) {
var myArray = [];
$("select").each(function() {
myArray.push($(this).val())
})
if (myArray.length != new Set(myArray).size) {
alert('validation failed');
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
</div>

How to set selected to option using ddSlick after postback?

I need to use image drop-down list from http://designwithpc.com/plugins/ddslick I am trying to set "selected" option after postback, but I get infinite loop of postbacks. Here is my code:
<form id="form1">
<select id="localeId" name="localeId"></select>
</form>
<script type="text/javascript">
//Dropdown plugin data
var ddData = [
{
text: "English",
value: "en",
selected: false,
description: "English",
imageSrc: "/assets/img/flags-icons/en-flag.png"
},
{
text: "Portuguese",
value: "pt",
selected: false,
description: "Portuguese",
imageSrc: "/assets/img/flags-icons/pt-flag.png"
},
{
text: "Russian",
value: "ru",
selected: false,
description: "Russian",
imageSrc: "/assets/img/flags-icons/ru-flag.png"
},
{
text: "Spanish",
value: "es",
selected: false,
description: "Spanish",
imageSrc: "/assets/img/flags-icons/es-flag.png"
}
];
$('#localeId').ddslick({
data: ddData,
defaultSelectedIndex: 3,
onSelected: function (data) {
if (data.selectedIndex > 0) {
$('#hidCflag').val(data.selectedData.value);
$.cookie('lang', document.getElementById("hidCflag").value, { expires: 365 });
form1.submit();
}
}
});
</script>
Could please help me to solve it?
Calling:
$( '#demoSetSelected' ).ddslick( 'select', { index: i } );
will also trigger the "onSelected()" function you defined causing an infinite loop.
I solved the same problem by modifying the source file (jquery.ddslick.js) and adding a flag to disable the call to onSelected():
Change the select function to:
methods.select = function (options) {
return this.each(function () {
if (options.index)
selectIndex($(this), options.index, options.disableTrigger);
});
}
Modify selectIndex function definition from:
function selectIndex(obj, index) {
to:
function selectIndex(obj, index, disableTrigger) {
At the very end of the function selectIndex(...), change from:
if (typeof settings.onSelected == 'function') {
settings.onSelected.call(this, pluginData);
}
to:
if ( !disableTrigger ) {
if (typeof settings.onSelected == 'function') {
settings.onSelected.call(this, pluginData);
}
}
Then use instead:
$( '#demoSetSelected' ).ddslick( 'select', { index: i, disableTrigger: true } );
As an aside: to select by value instead of index, check out the code mentioned in:
https://github.com/prashantchaudhary/ddslick/issues/78
https://github.com/lunrfarsde/ddslick
It's a fork of dd-slick with the description part removed. But added select by value.
You may use plugin's select method like
$('#demoSetSelected').ddslick('select', {index: i });
to select a particular index.
As per ddSlick demo#4 on their website(http://designwithpc.com/plugins/ddslick#demo)

Select2.js: why is id the same as text on change for removed?

JSfiddle: http://jsfiddle.net/cjVSj/
I have a simple select2 with the range of possible tags set by the tags option and the preloaded tags set by values in the input field in the html.
When the on change event fires on the select2, the removed item seems to lose its id, reporting instead its text value.
To see the problem, adding a tag (e.g. west) correctly reports the added.id, but removing the existing east tags reports id = east, not 1356.
Any insight into how to gain access to the id of a tag upon removal?
HTML:
<script>
var tags = [{ "id": 1354, "text": "north", "restricted": false
}, {"id": 1355, "text": "south", "restricted": false
}, {"id": 1356, "text": "east", "restricted": false
}, {"id": 1357, "text": "west", "restricted": false
}];
</script>tags:
<input type="text" id="mytags" value="east" />
JS:
$(document).ready(function () {
$('#mytags').select2({
placeholder: 'Search',
allowClear: true,
minimumInputLength: 2,
multiple: true,
tags: tags,
tokenSeparators: [','],
});
$('#mytags').on("change", function (e) {
console.log("change " + JSON.stringify({
val: e.val,
added: e.added,
removed: e.removed
}));
if (e.added) {
alert('added: ' + e.added.text + ' id ' + e.added.id)
} else if (e.removed) {
alert('removed: ' + e.removed.text + ' id ' + e.removed.id)
}
});
});
There was an issue with your select2 declaration and syntax.
Further more, if you entered any other text, say "eas" or "test", your piece of code reflected that as it is. Check this scenario.
Updated fiddle: http://jsfiddle.net/ZBf5H/
To be specific, you did not give appropriate mapping to your tags. Please find how to access remote data in select 2 from here
The change of code is as below:
$(document).ready(function() {
var data=[{id:1354,text:'north',restricted:false},
{id:1356,text:'east',restricted:false},
{id:1357,text:'west',restricted:false},
{id:1355,text:'south',restricted:false}];
function format(item)
{ return item.text; }
$('#mytags').select2({
placeholder: 'Search',
allowClear: true,
minimumInputLength: 2,
multiple: true,
tags: tags,
tokenSeparators: [','],
data:{ results: data, text: 'text' },
formatSelection: format,
formatResult: format
});
Let me know if this works for you.
Ok... I've got a working solution, but I still don't exactly understand the difference between select2's tags and data options....
JSfiddle: http://jsfiddle.net/7e8Pa/
I'm initializing select2 with a list of all possible tags via the data option from an array, then selecting those for preloading: the initSelection function checks for ids in the and looks them up in the data array (the pre-stored one, not Select2's). Last, new tags may be added (the createSearchChoice does this). To hook this to my server, I'm just going to insert ajax calls where noted below in the on-change event handler (which gets called after createSearchChoice, and can overwrite the field values for the new object set in createSearchChoice).
JS:
function findWithAttr(array, attr, value) {
for (var i = 0; i < array.length; i += 1) {
if (array[i][attr] == value) {
return array[i];
}
}
}
$(document).ready(function () {
function format(item) {
return item.text;
}
$('#mytags').select2({
placeholder: 'Search',
minimumInputLength: 2,
multiple: true,
//tags: tags,
tokenSeparators: [','],
data: {
results: tags,
text: 'text'
},
initSelection: function (element, callback) {
var data = [];
$($('#mytags').val().split(",")).each(function (i) {
var o = findWithAttr(tags, 'id', this);
if (o) {
data.push({
id: o.id,
text: o.text
});
} else {
console.log("findWithAttr returned none; likely invalid id");
}
});
console.log("data = " + JSON.stringify(data));
callback(data);
},
createSearchChoice: function (term, data) {
console.log("create");
if ($(data).filter(function () {
return this.text.localeCompare(term) === 0;
}).length === 0) {
// call $.post() to add this term to the server, receive back id
// return {id:id, text:term}
// or detect this shiftiness and do it below in the on-change
return {
id: -1,
text: term
};
}
},
formatSelection: format,
formatResult: format
});
$('#mytags').on("change", function (e) {
console.log("change " + JSON.stringify({
val: e.val,
added: e.added,
removed: e.removed
}));
if (e.added) {
alert('added: ' + e.added.text + ' id ' + e.added.id);
//modifying the id here overrides what is assigned above in createSelection
e.added.id = 5;
} else if (e.removed) {
alert('removed: ' + e.removed.text + ' id ' + e.removed.id);
}
var selections = (JSON.stringify($('#mytags').select2('data')));
$('#selectedText').text(selections);
});
});
HTML:
<script>
var tags = [{
"id": 1354,
"text": "north",
"restricted": false
}, {
"id": 1355,
"text": "south",
"restricted": false
}, {
"id": 1356,
"text": "east",
"restricted": false
}, {
"id": 1357,
"text": "west",
"restricted": false
}];
</script>
<p>tags:
<input type="text" id="mytags" value="1355" style="width:80%" />
</p>
<p>Selected Options: <span id="selectedText"></span>
</p>
<p>Debug: <span id="debug"></span>
</p>

Kendo Grid Draggable Rows With Kendo Template

I'm going to implement drag and drop behaviour with kendo grid which is populated using template. How can I achieve draggable rows and reordering with kendo grid.
.Orderable()
Works a treat. Maybe try ".Dragable()" I'm a bit unsure about that though.
Take a look at following my demo code and try it to implement.
var data = [
{ id: 1, text: "text 1", position: 0 },
{ id: 2, text: "text 2", position: 1 },
{ id: 3, text: "text 3", position: 2 }
]
var dataSource = new kendo.data.DataSource({
data: data,
schema: {
model: {
id: "id",
fields: {
id: { type: "number" },
text: { type: "string" },
position: { type: "number" }
}
}
}
});
var grid = $("#grid").kendoGrid({
dataSource: dataSource,
scrollable: false,
columns: ["id", "text", "position"]
}).data("kendoGrid");
grid.table.kendoDraggable({
filter: "tbody > tr",
group: "gridGroup",
hint: function(e) {
return $('<div class="k-grid k-widget"><table><tbody><tr>' + e.html() + '</tr></tbody></table></div>');
}
});
grid.table/*.find("tbody > tr")*/.kendoDropTarget({
group: "gridGroup",
drop: function(e) {
var target = dataSource.get($(e.draggable.currentTarget).data("id")),
dest = $(e.target);
if (dest.is("th")) {
return;
}
dest = dataSource.get(dest.parent().data("id"));
//not on same item
if (target.get("id") !== dest.get("id")) {
//reorder the items
var tmp = target.get("position");
target.set("position", dest.get("position"));
dest.set("position", tmp);
dataSource.sort({ field: "position", dir: "asc" });
}
}
});
put .Dragable()
but make sure that you sit it in the right place, the ordering is required. Some times you may not get the expected result and that may happen due to not paying attention to the order.

Categories