Add attributes to the selected list items in select2 - jquery-select2-4

Here is a working jsfiddle. I wish to add attributes (in particular id) to the <li> elements created. My use case is slightly different from the fiddle, rather than using an array, I am getting my data from ajax. In addition I want to give my users flexibility to create new tags if the same are not present in database. To save newly created item list having id's is a much better handle than just plain classes. Can I modify the attributes of the <li> elements created?
My actual code is something like this:
$(".js-data-example-ajax").select2({
ajax : {
url : "/content/search_skills",
dataType : 'json',
delay : 250,
data : function(params) {
return {
q : params.term, // search term
page : params.page
};
},
processResults : function(data, params) {
params.page = params.page || 1;
return {
results : data.items,
pagination : {
more : (params.page * 5) < data.total_count
}
};
},
cache : true
},
escapeMarkup : function(markup) {
return markup;
}, // let our custom formatter work
minimumInputLength : 1,
templateResult : formatRepo,
templateSelection : formatRepoSelection,
tags : true,
createTag : function (params) {
return {
id: params.term,
text: params.term,
newOption: true
}
},
});
function formatRepo(repo) {
if (repo.loading)
return repo.text;
var markup = '<ul class="list-group clear-list m-t">' + '<li class="list-group-item fist-item"><span class="pull-right">' + repo.id + '</span> <span class="label label-success">' + repo.count + '</span> ' + repo.text + '</li>';
return markup;
}
function formatRepoSelection (repo) {
var markup = repo.text;
return markup;
}
And my jsp (html) is:
<select class="js-data-example-ajax" style="width: 100%" multiple="multiple">
//Iterating through database query result to pre-load option items
<option value="<%=skill_objective.get("id")%>" selected="selected"><%=skill_objective.get("id")%> <%=skill_objective.get("name") %></option>
</select>

Here is a working solution:
$(".js-data-example-ajax").select2('data') will give me a hash of all the objects selected.

Related

select2+ASP.NET+MVC set values back to dropdown in edit mode

i am using select2 plugin with ASP.NET+MVC with multiple select option. i am able to save values into database of selected item. now I want to show those values (basically text which associate with those saved ids) into dropdown which has select2 plugin in edit mode.
how can i do that. below is my code.
$(document).ready(function () {
/* below values want to set to dropdown list
var selectedValue1 = '43,48,47,57';
$('#ddlCity1').select2({
multiple: true,
placeholder: "Select City",
allowClear: true,
tags: false, //prevent free text entry
width: "100%",
ajax: {
dataType: 'json',
delay: 250,
url: '#Url.Action("GetCityList", "DemoMVC")',
data: function (params) {
return {
searchTerm: params.term
};
},
processResults: function (data) {
var newData = [];
$.each(data, function (index, item) {
newData.push({
//id part present in data
id: item.Id,
//string to be displayed
text: item.City
});
});
return { results: newData };
},
cache: true
},
formatResult: function (element) {
return element.text + ' (' + element.id + ')';
},
formatSelection: function (element) {
return element.text + ' (' + element.id + ')';
},
escapeMarkup: function (m) {
return m;
},
});
$(".city1").on("select2:select", function (e) {
currentSelectedVal = $(e.currentTarget).val();
console.log(currentSelectedVal) // get selected values
});
$('.city1').on('select2:unselect', function (e) {
currentSelectedVal = $(e.currentTarget).val();
console.log(currentSelectedVal) // get selected values
});
});
//Dropdown with select2 control
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<label>City</label>
<select id="ddlCity1" class="city1" style="width:500px"></select>
</div>
</div>
</div>

How to set columns dynamically in Kendo template

How to set columns dynamically in Kendo template for kendo grid.In my kendo grid,columns are subject to change dynamically based on user preference.How to dynamically create Kendo Template?I am using Kendo JavaScript,I can switch to Kendo MVC if same thing i can achieve there.Is there any other approach to achieve this?
<script id="rowTemplate" type="text/x-kendo-template">
<tr class="k-master-row">
<td>
<div>#=column1#</div>
</td>
<td><span class="mydesign" title="column2#"</span></td>
<td>#column3#</td>
<td>#=column4#</td>
</tr>
</script>
Edit : In Kendo grid, we are dynamically setting the columns. Now issue is how do we set the dynamic width for content table and the header table. If it exceeds the max width how do we enable the horizontal scroll bar. Is there any approach to achieve this?
I'm not using kendo for MVC but I can still explain how to do this using regular kendo functions.
Basically, you can create a new kendo template instance by passing an html string to kendo.template. Then you can assign the new template instance to the grid's rowTemplate (or altRowTemplate) then call dataSource.read() to force a grid refresh.
You can generate your own html string or update an existing template in your page then use the jquery's html() to convert it into a string.
Ex:
var htmlTemplate = '';
if (userPreferences.likeRed) {
htmlTemplate ='<tr class="k-master-row"><td style="background-color:red">#column1#</td></tr>'
} else {
htmlTemplate ='<tr class="k-master-row"><td style="background-color:green">#column1#</td></tr>'
}
$("#grid").data("kendoGrid").rowTemplate = kendo.template(htmlTemplate);
$("#grid").data("kendoGrid").dataSource.read();
In order to format Kendo Grid column value with conditionally chosen action you can use one of the suitable examples below. For more information: How Do I Have Conditional Logic in a Column Client Template?
Here are some of the usage samples below. You can easily generate different templates with the help of this approach.
UI for Javascript:
{
field: "EmployeeName", type: "string", width: "55px", title: "Employee Name",
template: "#= GetEditTemplate(data) #"
}
UI for MVC:
...
columns.Bound(t => t.EmployeeName)
.Title("Status Name")
.Template(#<text></text>)
.ClientTemplate("#= GetEditTemplate(data)#")
.Width("55px");
...
Example I: In this example, Model is passed to the Javascript method by using "data" property and the model property is used in the "if" condition.
<script>
//Change the color of the cell value according to the given condition
function GetEditTemplate(data) {
var html;
if (data.StatusID == 1) {
html = kendo.format(
//"<a class=\"k-button\" href='" + '#Url.Action("Edit1", "Controller")' + "/{0}" + " '>Edit</a> ",
"<span class='text-success'>" +
data.EmployeeName
+ "</span>"
);
}
else {
html = kendo.format(
//"<a class=\"k-button\" href='" + '#Url.Action("Edit2", "Controller")' + "/{0}" + " '>Edit</a> ",
"<span class='text-danger'>Cancel</span>"
);
}
return html;
}
</script>
Example II:
<script>
function Getvalue(value) {
// console.log(value);
if (value && value != null && value.indexOf("A") == 0)
return "<b style='color:red'>" + value + "</b>";
else
return "";
}
$(document).ready(function () {
$("#grid").kendoGrid({
dataSource: localDataSource,
columns: [
{
field: "FirstName",
title: "First Name", template: '#=Getvalue(FirstName)#'
}
],
});
});
</script>
Hope this helps...
This will work in ASP.NET MVC/Razor, if you prepare a collection of the dynamic columns definitions in advance, then put them in the view model for the cshtml. Then loop through the collection and insert the field name that will match the datasource, header title, desired width, etc...
$("#grid-quick").kendoGrid({
pageable: {
pageSizes: [10, 20, 50, 100]
},
sortable: { mode: "multiple" },
columns: [
#{
foreach (var col in Model.Columns)
{
#:{ field: "#col.Name.Replace(".","_")", width: "#col.Width" + "px" },
}
}
],
filterable: false,
dataSource: {
serverPaging: true,
serverSorting: true,
pageSize: 20,
type: 'aspnetmvc-ajax',
schema: {
data: "Data",
total: "Total",
model: {
fields: {
#{
foreach (var col in Model.Columns)
{
#: "#col.Name.Replace(".","_")" : { type: "string" },
}
}
}
}
},
transport: {
read: {
url: oVariables.baseURL + "Query/DynamicResults",
dataType: "json",
type: "post"
}
}
}
});

Select2 Dropdown autoselect if only 1 option available

I have a select2 dropdown box using remote datasource.
What I would like to do is if/when there is only one option returned by the search, auto select it. ie, the user doesn;t have to click on the option to make the selection.
$("#searchInfo_Entity_Key").select2({
ajax: {
url: "/Adjustment/GetEntity",
dataType: 'json',
delay: 250,
data: function (params) {
return {
term: params.term, // search term
};
},
processResults: function (data) {
return {
results: data
};
},
results: function (data) {
return { results: data };
},
},
initSelection: function (element, callback) {
var data = [];
callback(data);
},
minimumInputLength: 2,
allowClear: true,
placeholder: "Select an entity"
});
This is a custom matcher, that wraps around the default matcher and counts how many matches there are. If there is only one match, then it will select that match, change it, and close the dropdown box.
(Not tested with remote data.)
$(function() {
var matchCount = 0; // Track how many matches there are
var matched; // Track the ID of the last match
$('select').select2({
placeholder: 'Product Search',
allowClear: true,
matcher: function(params, data) {
// Wrap the default matcher that we have just overridden.
var match = $.fn.select2.defaults.defaults.matcher(params, data);
// If this is the first option that we are testing against,
// reset the matchCount to zero.
var first = $(data.element).closest('select').find('option').first().val();
if (first == data.id) matchCount = 0;
// If there was a match against this option, record it
if (match) {
matchCount = matchCount + 1;
matched = data.id;
}
// If this is the last option that we are testing against,
// now is a good time to check how many matches we had.
var last = $(data.element).closest('select').find('option').last().val();
if (last == data.id && matchCount == 1) {
// There was only one match, change the value to the
// matched option and close the dropdown box.
$(data.element).closest('select')
.val(matched).trigger('change')
.select2('close');
return null;
}
// Return the default match as normal. Null if no match.
return match;
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.full.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet"/>
<select style="width: 20em">
<option value=""></option>
<option value="100">Product One</option>
<option value="200">Product Two</option>
<option value="300">Product Three</option>
<option value="400">Product Four</option>
<option value="500">Product Five</option>
</select>

Unable to show "Searching" when using select2 (Loading remote data)

Refer to https://select2.github.io/examples.html, text "Searching" is shown when the remote data is loading. However, I don't know why "undefined" is shown in my case.
This is the css file.
<div class="col-sm-9">
<select class="js-data-example-ajax form-control" style="width:100%;">
<option value="select2/select2" selected="selected">select2/select2</option>
</select>
</div>
And the setting of ajax call
$(".js-data-example-ajax").select2({
ajax: {
url: "/search/products",
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term,
page: params.page
};
},
processResults: function (data, page) {
return {
results: data.items
};
},
cache: true
},
minimumInputLength: 1,
templateResult: formatProduct,
templateSelection: formatProductSelection
});
Result:
function formatRepo (repo) {
if (repo.loading) return repo.text;
var markup = '<div class="clearfix">' +
'<div class="col-sm-1">' +
'<img src="' + repo.owner.avatar_url + '" style="max-width: 100%" />' +
'</div>' +
'<div clas="col-sm-10">' +
'<div class="clearfix">' +
'<div class="col-sm-6">' + repo.full_name + '</div>' +
'<div class="col-sm-3"><i class="fa fa-code-fork"></i> ' + repo.forks_count + '</div>' +
'<div class="col-sm-2"><i class="fa fa-star"></i> ' + repo.stargazers_count + '</div>' +
'</div>';
if (repo.description) {
markup += '<div>' + repo.description + '</div>';
}
markup += '</div></div>';
return markup;
}
function formatRepoSelection (repo) {
return repo.full_name || repo.text;
}
$ajax.select2({
ajax: {
url: "https://api.github.com/search/repositories",
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term, // search term
page: params.page
};
},
processResults: function (data, params) {
// parse the results into the format expected by Select2
// since we are using custom formatting functions we do not need to
// alter the remote JSON data, except to indicate that infinite
// scrolling can be used
params.page = params.page || 1;
return {
results: data.items,
pagination: {
more: (params.page * 30) < data.total_count
}
};
},
cache: true
},
escapeMarkup: function (markup) { return markup; },
minimumInputLength: 1,
templateResult: formatRepo,
templateSelection: formatRepoSelection
});
complete code which loads repositories in select 2 you can alter this code according to your requirements
my select box with multiple select
<select id="to_users" name="to_users" class="form-control js-data-example-ajax" multiple="multiple">
</select>
you can format results
processResults: function(data, page) {
// parse the results into the format expected by Select2.
// since we are using custom formatting functions we do not need to
// alter the remote JSON data
return {
results: $.map(data, function(obj) {
return { id: obj.user_id, text: obj.name };
})
//results: data
};
},
if you are formatting results to select2 behaviour then disable code
/* escapeMarkup: function(markup) {
return markup;
}, // let our custom formatter work
templateResult: formatRepo, // omitted for brevity, see the source of this page
templateSelection: formatRepoSelection // omitted for brevity, see the source of this page*/
Please try
function formatRepo(repo) {
if (repo.value == undefined) {
repo.value = 'Loading...'
}
var markup = '<div class="clearfix">' + repo.value + '</div>'
return markup;
}
There is a possible workaround for the above issue. Feel free to make comments.
Here is the code I've written before, let say the return JSON is {"items":[{"id":1,"name":"Product1"},{"id":2,"name":"Product2"}]}
var formatProduct = function(data){
return '<div>'+(data.name)+'</div>';
}
I've modified the code as follow and the 'Searching...' text shows again:
var formatProduct = function(data){
return '<div>'+(data.name || data.text)+'</div>';
}
In select2.js, line 798, when the data is remotely loading
this.template(data, option);
this.template directs to select2.js line 1058
Results.prototype.template = function (result, container) {
var template = this.options.get('templateResult');
container.innerHTML = template(result);
};
// result is an object indicating whether the data is loading.
// {disabled: true, loading: true, text: "Searching…"}
the template here takes the custom parameter 'templateResult' and generate the text, therefore, the custom function must contain data.text, otherwise it returns underfined.
In my case it was the formatProduct function (it has a different name in my code, but it's the same thing).
Let's say you call formatProduct for templateResult:
templateResult: formatProduct
In this case you have to check what formatProduct returns, like:
function formatProduct(product) {
return product.name || product.text;
}
In my case I was returning always product.name and the "Searching" text was under product.text, so I had to check to display it when no product was being found yet.

Auto-complete doesn't work as expected

I tried to implement this in MVC 5 with jquery ui 1.10.2
#{
ViewBag.Title = "Home Page";
Layout = null;
}
<p>
Enter country name #Html.TextBox("Country")
<input type="submit" id="GetCustomers" value="Submit" />
</p>
<span id="rData"></span>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery-ui.js"></script>
#Styles.Render("~/Content/themes/base/css")
<script type="text/javascript">
$(document).ready(function () {
$("#Country").autocomplete({
source: function (request, response) {
$.ajax({
url: "/Home/AutoCompleteCountry",
type: "POST",
dataType: "json",
data: { term: request.term },
success: function(data) {
response($.map(data, function(item) {
return { label: item.Country, value: item.Country };
}));
}
});
}
});
})
</script>
the server side is
...
[HttpPost]
public JsonResult AutoCompleteCountry(string term)
{
// just something to return..
var list = new List<string>() { "option1", "option2", "option3"};
var result = (from r in list
select r);
return Json(result, JsonRequestBehavior.AllowGet);
}
}
I have two issues
1. it open up drop down autocomplete with 3 dots but without the actual strings.
2. It has this annoying message of "3 results were found" - I'd like to eliminate it..
DO you have any idea how to face those two issues or neater way to implement it in MVC5?
The 3 bullet points and "3 results were found" is because you are missing the jQuery UI css file. That file will format a drop down that will look a lot better. You can customize how the dropdown looks with additional css.
Also, you are seeing 3 empty results because your JS is referencing item.Country ...
return { label: item.Country, value: item.Country };
But your server code is just sending 3 strings.
new List<string>() { "option1", "option2", "option3"};
To fix, change your JS to just reference the item (the string) ...
return { label: item, value: item};
OR, change your server code to send more complex objects
new List<Object>() { new { Country = "option1" }, new { Country = "option2" }, new { Country = "option3" } };
use return data in place of return { label: item.Country, value: item.Country };

Resources