select2 4.0 brings older list in suggestion with query method and minimumInputLength not taking effect - jquery-select2-4

I am in process of upgrading select2 version 3.5.1 to 4.0. I required to use query method for mandate.
There are two specific problem arises
minimumInputLength is not taking effect
When user focus searchbox, The past results are displayed with Searching.. is first item. (If I assign empty result then it resolves the problem but then it displays No results found message)
Please refer to my code snippet below.
var self = this, $view = $(view);
$.fn.select2.amd.require(['select2/data/array', 'select2/utils', 'select2/data/minimumInputLength'], function (ArrayData, Utils, MinimumInputLength) {
function CustomData($element, options) {
CustomData.__super__.constructor.call(this, $element, options);
this.options = options;
}
Utils.Extend(CustomData, ArrayData);
CustomData.prototype.query = function (params, callback) {
//callback({ results: [] });
self.searchText(params.term);
q(ko.unwrap(self.qPromise)).then(function () {
var select2data = $.map(ko.unwrap(self.dataSource), function (obj) {
obj.id = obj.id || obj.Id + obj.KeyDoc;
obj.text = obj.text || obj.Headline;
return obj;
});
callback({ results: select2data });
});
}
// Decorate after the adapter is built
Utils.Decorate(CustomData, MinimumInputLength);
$view.select2({
dataAdapter: CustomData,
multiple: ko.unwrap(self.multiple),
templateResult: ko.unwrap(self.formatFunc),
escapeMarkup: function (markup) { return markup; },
dropdownParent: $('.' + ko.unwrap(self.containerClass)),
placeholder: ko.unwrap(self.placeHolderCaption),
minimumInputLength: 1,
allowClear: true
});
});
Every time I wish to assign new options in suggestion list (no cached no stored)
Please suggest workaround.
Thanks in advanced

Related

select2 (remote data) throws exception because of typing to fast

I'm using select2 for loading remote data. I declared the minimumInputLength to 3 letters, so after that it will start searching.
Whenever I hit the fourth letter while typing fast I get an Javascript exception saying :
Sorry. An error occured while communicating with the server. Please try again later.
How can I avoid this? I already changed the quietMillis (waitTimesMs) to lower or higher (does this even have something to do with it?).
Every help is appreciate.
My code is like:
$(function () {
$("#Search").select2({
minimumInputLength: 3,
ajax: {
url: site,
dataType: "json",
quietMillis: waitTimeMs,
data: function (params) {
var page = (params.page || 1) - 1;
return {
searchText: params.term,
pageCount: 10,
page: page
};
},
processResults: function (data) {
var select2Data = $.map(data.Items, function (obj) {
obj.id = obj.ID;
obj.text = obj.Name;
return obj;
});
return {
results: select2Data,
pagination: { more: (data.PageNo * 10) < data.TotalCount }
};
}
Finally it works!
select2 changed "quietMillis" to "delay" so I could change quietMillis as big as I wanted and nothing changed at all...

Cached autocomplete with Solr

I'm using jQuery-ui and Solr to make a neat search box with auto-complete. The query seems to work well but the results aren't actually displayed in my search box. Here is the code I'm using:
var cache = {};
$("#Keyword").autocomplete({
minLength: 3,
source: function(request, response) {
var term = request.term;
if(term in cache) {
response(cache[term]);
return;
}
$.getJSON("http://127.0.0.1:8080/solr/terms/?terms=true&terms.fl=ctnt_val&wt=json&indent=on&terms.prefix=" + $("#Keyword").val(),
request,
function(data, status, xhr) {
cache[term] = data;
response(data);
});
}
});
So my best guess is that I'm not treating the returned values correctly. How could I make them appear properly underneath my search box?
I was able to determine what was wrong in my return function : I wasn't looping properly through the results. Best way is to use the map function to iterate through them.
$("#Keyword").autocomplete({
minLength: 3,
source: function(request, response) {
$query = "http://127.0.0.1:8080/solr/terms/?jsoncallback=?&terms=true&terms.prefix=" + $("#Keyword").val();
$.getJSON($query,
request,
function(data) {
response($.map(data.terms.ctnt_val, function(item) {
return item;
}));
}
);
}
});

Select2 - Infinite loop with trigger('change')

Here is my case:
$('select').select2();
$('select').on('change', function () {
// calling a function
myFunction();
});
function myFunction() {
// changes my select values
// so I need to update the select for seing the news values
$('select').trigger('change');
// hehe I fire the change event so myFunction is called again and again
}
What can I do to avoid that behavior? Regards...
This is a bug in Select2. I had the same issue with the following code:
var FID = $(location).attr('href').split("/")[5];
$('#facility').children().each(function () {
if ($(this).val().trim() == FID.trim()) {
$(this).attr('selected', 'selected').trigger('change');
}
});
The following isn't ideal, but it does fix the issue. Note that you will need to redefine your Select2 options (mine shown).
var FID = $(location).attr('href').split("/")[5];
$('#facility').children().each(function () {
if ($(this).val().trim() == FID.trim()) {
$(this).attr('selected', 'selected');
$('#facility').select2({
placeholder: "",
minimumResultsForSearch: -1
});
}
});

knockout validation - advanced search user interface

I am building an advanced search UI similar to the TFS query builder web interface. Using knockout for the client side implementation and have everything more or less working except the final validation to make certain required items are basically selected. It sort-of works as far as giving me a validation error if I select an item and then de-select the item. Which is fine, but I would like to have the form validate when hitting the search button.
I am pretty sure I need to make use of the ko.validatedobservable method, I'm just not sure exactly how. Anyway, I have a fiddle to look at: http://jsfiddle.net/sstolp/uXBSA/ if anyone has the time or inclination to help me out. I would deeply appreciate it.
Thank you for your time.
scvm.SearchLine = function () {
var self = this;
self.selectedField = ko.observable().extend({ required: true });
self.selectedOperator = ko.observable().extend({ required: true });
self.firstdate = ko.observable(new Date());
self.lastdate = ko.observable(new Date());
self.thedate = ko.observable(new Date());
return self;};
scvm.Criteria = function () {
var self = this,
lines = ko.observableArray([]),
// Put one line in by default
loadInitialData = function () {
lines.push(new scvm.SearchLine());
},
rowcount = ko.computed(function () {
return lines().length;
}),
// Operations
addLine = function () {
lines.push(new scvm.SearchLine());
},
removeLine = function (line) {
lines.remove(line);
},
search = function () {
var data = $.map(lines(), function (line) {
return line.selectedField() ? {
selectedField: line.selectedField().searchfield,
selectedOperator: line.selectedOperator().name,
} : undefined
});
alert("Send to server: " + JSON.stringify(data));
},
clear = function () {
lines.removeAll();
};
return {
lines: lines,
loadInitialData: loadInitialData,
rowcount: rowcount,
addLine: addLine,
removeLine: removeLine,
search: search,
clear: clear
};
}();
Yes, all your SearchLine objects must be wrapped into ko.validatedObservable. Also you should implement computed property which will check isValid() for each criteria line and return global validity flag.
scvm.SearchLine = function () {
var self = this;
self.selectedField = ko.observable().extend({ required: true });
self.selectedOperator = ko.observable().extend({ required: true });
self.firstdate = ko.observable(new Date());
self.lastdate = ko.observable(new Date());
self.thedate = ko.observable(new Date());
return ko.validatedObservable(self);
};
scvm.Criteria = function () {
// ...
return {
lines: lines,
loadInitialData: loadInitialData,
rowcount: rowcount,
addLine: addLine,
removeLine: removeLine,
search: search,
clear: clear,
// new property that indicates validity of all lines
linesValid: ko.computed(function(){
var items = lines();
for (var i = 0, l = items.length; i < l; i++)
if (!items[i].isValid()) return false;
return true;
})
};
}();
This new property can be used in enable binding of you "Search" button:
<input type="button"
data-bind="enable: linesValid, click: search"
title="Clicking this button will run a search."
value="Search" />
I've modified your fiddle. Take a look: http://jsfiddle.net/ostgals/uXBSA/8/
Update:
Also we should slightly modify Criteria.search method, since our line array contains observables rather than objects:
//...
search = function () {
var data = $.map(lines(), function (line) {
line = ko.utils.unwrapObservable(line);
return line.selectedField() ? {
selectedField: line.selectedField().searchfield,
selectedOperator: line.selectedOperator().name,
} : undefined
});
alert("Send to server: " + JSON.stringify(data));
},
//...

Calling controller method from JQuery calls occurs twice and also returning error?

Hi guys i have posted a similar post before, but that is for another, now i face a strange and odd issue with my Jquery code. Here i was calling a controller method using Jquery but it is calling twice , so that may cause two entries in my db. Here is what i have written in my JQuery
<script type="text/javascript">
$('#btnSubmit').click(function () {
var instructorUrl = '#Url.Action("ApplyToBecomeInstructor", "InstructorApplication")';
var currentUser = '#Model.CurrentUserId';
var user = [];
var educationList = [];
var experience = $('#Experience').val();
var isWilling = $('#WillingToTravel').is(":checked");
$('#editorRows .editorRow').each(function () {
var education = {
UniversityOrCollege: $(this).find('.university').val(),
AreaOfStudy: $(this).find('.area').val(),
Degree: $(this).find('.degree').val(),
YearReceived: $(this).find('.year').val()
}
educationList.push(education);
});
var applicationFromView = {
EducationalBackgrounds: educationList,
CurrentUserId: currentUser,
Experience: experience,
WillingToTravel: isWilling
}
$.ajax({
type: 'POST',
url: instructorUrl,
dataType: 'JSON',
async: false,
data: JSON.stringify(applicationFromView),
contentType: 'application/json; charset=utf-8',
success: function (data) {
return false;
},
error: function (data) {
alert(xhr.status);
alert(thrownError);
alert(xhr.responseText);
return false;
}
});
});
</script>
and my controller action looks like this
[HttpPost]
public ActionResult ApplyToBecomeInstructor(InstructorApplicationViewModel applicationFromView)
{
Student thisStudent = this.db.Students.Where(o => o.StudentID == applicationFromView.CurrentUserId).FirstOrDefault();
List<PaulSchool.Models.EducationalBackground> educationList = new List<EducationalBackground>();
foreach (var educate in applicationFromView.EducationalBackgrounds)
{
var education = new Models.EducationalBackground
{
YearReceived = educate.YearReceived,
Degree = educate.Degree,
AreaOfStudy = educate.AreaOfStudy,
UniversityOrCollege = educate.UniversityOrCollege
};
educationList.Add(education);
}
var instructorApplication = new InstructorApplication
{
BasicInfoGatheredFromProfile = thisStudent,
Experience = applicationFromView.Experience,
EducationalBackground = new List<Models.EducationalBackground>(),
WillingToTravel = applicationFromView.WillingToTravel
};
instructorApplication.EducationalBackground.AddRange(educationList);
this.db.InstructorApplication.Add(instructorApplication);
this.db.SaveChanges();
return this.Redirect("Index");
}
Error message showing is JSON Parsing error.. but it is confusing to me.
I really wondered why this is happening, can anybody please take a look and help me?
This is what your code does:
$('#btnSubmit').click(function () { // attach a click handler for the button.
...
...
// Look for elements inside the button...
UniversityOrCollege: $(this).find('.university').val(),
Change from click to submit:
$('#formId').submit(function (e) {
...
// Now "this" is the form - not the button.
// Look for elements inside the <form>
UniversityOrCollege: $(this).find('.university').val(),
// Prevent the default form submition
return false // Or: e.preventDefault();
Another tip: use jQuery serialize function.
$('#btnSubmit').click() will fire every time the button is pressed. Often users double click buttons even though it only needs a single click or if you don't give any indication that something is happening they get impatient and click it again. You need some way to determine if the request has been made. There's ways to do this client and server side. The easiest client side way is to disable the button to prevent multiple clicks:
$('#btnSubmit').click(function () {
// Disable the button so it can't be clicked twice accidentally
$('#btnSubmit').attr('disabled', 'disabled');
//...
$.ajax({
//...
complete: function() {
// Make sure we re-enable the button on success or failure so it can be used again
$('#btnSubmit').removeAttr('disabled');
}
});
});

Resources