Make Select2 fetch data only once - jquery-select2

I'm using Select2 builtin AJAX to load a tiny list of items. Select2 loads the entire list on first selection (good) but reloads the JSON feed every time the user tries to change his selection or type to filter items (and that means a new AJAX request for each typed letter!).
At A request is being triggered on every key stroke, can I delay this? we can read:
By default, Select2 will trigger a new AJAX request whenever the user
changes their search term. You can set a time limit for debouncing
requests using the ajax.delay option.
$('select').select2({
ajax: {
url: '/example/api',
delay: 250
}
});
This will tell Select2 to wait 250 milliseconds before sending the request out to your API.
... but it doesn't. Seriously. I've also tried the undocumented minimumInputLength property shown in examples but it doesn't seem to do anything.
Is it even possible to make Select2 fetch data only once?

The select2 ajax parameter sets off the ajax call every time the user changes her/his input. If you want to load your list only once, just load it via a normal ajax call when your page is loaded and set the result into the data attribute of your select2 like this:
var dataList;
$.ajax({
url : '/example/api',
success : function(data) {
dataList = data;
},
async : false
});
$('select').select2({
data: dataList
});

It is working for me. I tested it using a large delay: delay: 3000
The AJAX reqeust is indeed delayed 3 secs after the last keystroke.
It also works when deleting characters with the backspace key.
I'm using select2.full.js v4.0.3. Hope this helps.

Let me know if this solution would work for you:
1) bind an onChange action to your select element:
<select name="variable" onChange="loadyourlist($('option:selected',this).val());">
<option value="#">Select State</option>
<option value="1">State 1</option>
</select>
2) Make your request inside loadyourlist function, but check if it has been called before:
window.called = 0; //initial state
function loadyourlist(value){
if(!window.called){ //not called before
//make your ajax call
window.called = 1; //increment to avoid furter calls
}
}

Related

Setting initial value for select2 with ajax data source

I use select2 for specifying recipients for the website's inner messaging system. There are users and they can send messages to each other. They can search other users by the user name.
I use the following config:
this.$select2.select2({
multiple: true,
ajax: {
url: "/userSearch",
dataType: "json",
},
templateResult: function(data) {
var user = new SomeComplexUserModel(data);
var $div = $(<div></div>");
$div.append("<img src='"+user.image.readPaths().crop+"'>");
$div.append("<span>"+user.fullName()+"</span>");
return $div;
},
templateSelection: ..the same as templateResult..
Now I want to set initial value for this. How to do that? I have the list of ids of the users that have to be selected on page load. I make the separate request to /userSearch and receive the data. Then I'm trying to push this data to the select2 somehow.
I can't create native var opt = new Option(text,value); select.append(opt) because this case templateSelection gets only id and text from the option, it can't construct the user model based on this data only. It does not show users with avatars.
I tried to trigger select2:select event with {originalEvent:null,data:$.extend(ajaxResult,{selected:true,disabled:false,element:null},_type:"select")}, but it seems it does not work this direction. It emits events but is not subscribed for them.
I also tried to set this.$select2.val(ajaxData); this.$select2.trigger('change'), after select2 initialization, but it does not work either.

twitter typeahead only trigger in the beginning, never trigger again until reload the page

Whenever input the words into the twitter typeahead, it should allow me to remotely query the city.However, when I type the words in the first time, it triggers immediately. but after the first time, no matter how much I type into the typeahead, it never triggers again.
What is more, url:'/city?n='+$('.typeahead').val(), the server always receives the request with url on ' /city?n= ', so it seems $('.typeahead').val() doesn't work though the input filed has value in it.
<input class="typeahead" name="city" type="text" style="width:400px" placeholder="Search cities..." >
$('.typeahead').typeahead({
remote:{
url:'/city?n='+$('.typeahead').val()
,timeout: 2000
,cache:84000
,rateLimitWait:1000
}
});
try use the typeahead.js %QUERY wildcard to send query
$('.typeahead').typeahead({
remote:{
url:'/city?n=%QUERY',
timeout: 2000,
cache: 84000,
rateLimitWait: 1000
}
});
First Question: The reason why your typeahead does not work after the first query is because you might have made a mistake on server side, or client side, which crashed the page. Look into console if your request is being made each time or not and if the server is processing each request or not.
For your second question, I found this bug reported in typeahead that mentions that $('.typeahead').val() returns undefined. That might be the reason why your URL is not getting dynamically set.
try $('.tt-input').typeahead('val') instead.
.tt-input is the class inserted by the typeahead plugin.

Using changePage to Open a Dialog - Data object not sent

$.mobile.changePage("verify.aspx", { transition: "pop", role: "dialog", data: $("#form1").serialize() });
I'm using the above syntax to open a dialog box and in trying to send the form data via the data argument, nothing is passed.
This is what's being passed in the query string when I open the dialog:
#&ui-state=dialog&ui-state=dialog
(as a side note, this call is originating from a button within another dialog, thus the two ui-state=dialog's)
As you can see, no form data. Any ideas what I can do to persist the data in the url?
Answering my own question:
Found that the data-url attribute of the dialog you request is injected w/ the relative url.
By doing something like:
$("#dialog").on("pagebeforecreate", function (evt) {
var urlObj = $.mobile.path.parseUrl($(this).attr("data-url"));
Will give you access to the url and thus the proper query string values.

jQuery block UI exceptions

I am using JQuery UI plugin blockUI to block UI for every ajax request. It works like a charm, however, I don't want to block the UI (Or at least not show the "Please wait" message) when I am making ajax calls to fetch autocomplete suggest items. How do I do that? I am using jquery autocomplete plugin for autocomplete functionality.
Is there a way I can tell the block UI plug-in to not block UI for autocomplete?
$('#myWidget').autocomplete({
source: function(data, callback) {
$.ajax({
global: false, // <-- this is the key!
url: 'http:...',
dataType: 'json',
data: data,
success: callback
});
}
});
Hm, looks to be a missing feature in jquery :)
You could use a global flag to indicate if it is a autocomplete call and wrap it in a general autcompletefunction
var isAutoComplete = false;
function autoComplete(autocomplete){
isAutoComplete = true;
if($(autocomplete).isfunction())
autocomplete();
}
$(document).ajaxStart(function(){if(!isAutoComplete)$.blockUI();}).ajaxStop(function(){isAutoComplete = false;$.unblockUI();});
It's not a nice solution but it should work...
try using a decorator
$.blockUI = function() {
if (condition_you_dont_want_to_block) {
return;
}
return $.blockUI.apply(this, arguments);
}
or you can write your own block function that is smarter
function my_blockUI() {
if (condition_you_dont_want_to_block) {
return;
}
$.blockUI();
}
$(document).ajaxStart(my_blockUI).ajaxStop($.unblockUI);
You can set blockUI to work for all functions on the page by adding to a global jQuery event handler. To make sure it doesn't get called on autocomplete ajax calls we have to determine if the call is an autocomplete call or not. The problem is that these global functions don't have that much information available to them. However ajaxSend does get some information. It gets the settings object used to make the ajax call. the settings object has the data string being sent. Therefore what you can do is append to every data string in every ajax request on your page something like:
&notautocomplete=notautocomplete
For example:
$.ajax({data:"bar=1&foo=2&notautocomplete=notautocomplete"})
Then we can put this code in your document ready section before anything else:
$(document).ajaxSend(
function (event, xhr, ajaxOptions){
if(ajaxOptions.data.indexOf("notautocomplete") !== -1){
$.blockUI;
}
});
$(document).ajaxStop($.unblockUI);
Of course the other better idea would be to look for something unique in the auto complete requests, like the url, but that depends on which autocomplete plug-in you are using and how you are using it.
using a modal block (block UI) means blocking any inputs from user, I'd suggest plain old throbber to show 'Please wait..' and to block ( set attributes readonly="readonly" ) ur input controls till the ajax request is complete.
The above UI seems to be self conflicting!

jQuery Dialog posting of form fields

I'm trying to do some data entry via a jQuery modal Dialog. I was hoping to use something like the following to gather up my data for posting.
data = $('#myDialog').serialize();
However this results in nothing. If I reference just the containing form instead myDialog then I get all the fields on the page except those within my dialog.
What's the best way to gather up form fields within a dialog for an AJAX submission?
The reason this is happening is that dialog is actually removing your elements and adding them at root level in the document body. This is done so that the dialog script can be confident in its positioning (to be sure that the data being dialog'd isn't contained, say, in a relatively positioned element). This means that your fields are in fact no longer contained in your form.
You can still get their values through accessing the individual fields by id (or anything like it), but if you want to use a handy serialize function, you're going to need to have a form within the dialog.
I've just run into exactly the same problem and since I had too many fields in my dialog to reference them individually, what I did was wrap the dialog into a temporary form, serialize it and append the result to my original form's serialized data before doing the ajax call:
function getDialogData(dialogId) {
var tempForm = document.createElement("form");
tempForm.id = "tempForm";
tempForm.innerHTML = $(dialogId).html();
document.appendChild(tempForm);
var dialogData = $("#tempForm").serialize();
document.removeChild(tempForm);
return dialogData;
}
function submitForm() {
var data = $("#MyForm").serialize();
var dialogData = getDialogData("#MyDialog");
data += "&" + dialogData;
$.ajax({
url: "MyPage.aspx",
type: "POST",
data: data,
dataType: "html",
success: function(html) {
MyCallback(html);
}
});
}
Form element inside dialog is removed from form and moved to the end of the body. You need something like this.
$("#dialog_id").dialog().parent().appendTo($("#form_id"));
jQuery("#test").dialog({
autoResize:true,
width:500,
height:600,
modal: true,
bgiframe: true,
}).parent().appendTo("form");
This works like charm

Resources