select2 : cannot read property query of null - javascript

I have create javascript like this
$(document).on("select2:open", ".provider_suggestion", function() {
$(this).select2({
minimumInputLength: 2,
ajax: {
url: "../include/suggestion/provider_name.php",
dataType: 'json',
delay: 250,
data: function(params){ return { q: params.term }; },
processResults: function (data, page) { return { results: data }; },
cache: true
}
});
});
and create select html input like this
<select id="c_providers" name="c_providers" class="provider_suggestion" style="width:100%"></select>
and when page loaded, I click the select input.
I open the browser console, its mentioned that
Uncaught TypeError: Cannot read property 'query' of null
I still dont understand about this issue.

You must have already initialized the select2 somewhere previous to your provided code snippet, or I expect the select2:open listener would never fire and cause your problem. When I replicated the situation in a fiddle and peeked at the select2 source, it seemed that select2 was complaining about a dataAdapter being null, which must be a side effect of this double select2() call, or that the .select2() call is inside the listener with an unexpected context... Or something, don't have the time or interest to explore down to the root cause.
Regardless, moving the .select2() call out of the listener (and removing the then empty listener) removed the problem. Based on the limited information available in your question, it does not seem like there is any need at all to use this listener, at least the way you are using it. A simplistic working example is in this JSfiddle, where the only real difference to your original code is the removal of the listener wrapping (and the mocking of AJAX calls). So, try something like
$('#c_providers').select2({
minimumInputLength: 2,
ajax: {
url: "../include/suggestion/provider_name.php",
dataType: 'json',
delay: 250,
data: function(params){ return { q: params.term }; },
processResults: function (data, page) { return { results: data }; },
cache: true
}
});
as the only select2 initialization for this #c_providers element.

Related

Typeahead.js + Bloodhound remote data: how to get calling object reference?

I'm trying to DRY out some JQuery code that initializes a typeahead.js plugin that uses the Bloodhound suggestion engine with a remote data source. This is the code so far:
var locsData = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace("name"),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: "/locations/search.json?q=%QUERY",
ajax: {
beforeSend: function(xhr, settings) {
$("#typeahead1").addClass('loading-text');
},
complete: function(xhr, status) {
$("#typeahead1").removeClass('loading-text');
}
}
},
limit: 100
});
locsData.initialize();
$("#typeahead1").typeahead({
minLength: 3
}, {
name: "locs",
displayKey: "name",
source: locsData.ttAdapter()
});
I'm trying to generalize this code for a bunch of different text fields; that should not be a problem: I could use $(".myClass").typeahead({ ... }) and the plugin would be initialized for all of those controls. The problem I'm facing is with the ajax callback functions in the Bloodhound configuration (beforeSend, complete, etc.): I'm toggling a "loading.gif" class for the text field inside those functions, and I need that code to get a reference to the calling object.
How can I get a reference to the calling text field inside those callbacks? I need something like this:
$(<text-field reference>).addClass('loading-text');
I hope somebody could help me. Thanks in advance!
EDIT - For now I'm using the following code that somehow solves my problem, but the question about getting a calling object reference (the subject of this) is still pending.
if ($(document.activeElement).typeahead != null) {
$(document.activeElement).addClass('loading-text');
}

jQuery Select2 Plugin

I have a form that allows a user to enter information. It uses the select2 plugin.
On load, it is initiated to the visible form and works fine.
However, once I add a new div and run it again on all of the classes (original and added) it loses the values that were in the ones prior to adding a new one.
Is there a way to preserve this information when the plugin is run?
When you click on Add Vehicle, it inserts a new div and then runs the plugin again on the .carpool selector which is in each one of the divs.
$(".carpool").select2({
multiple: true,
allowClear: true,
placeHolder: 'Agent Last name',
minimumInputLength: 3,
ajax: {
url: "jsonUser.php",
dataType: 'json',
allowClear: true,
data: function (term) {
return {
term: term, // search term
};
},
results: function (data) { // parse the results into the format expected by Select2.
return {results: data};
}
},
});
Just run the plugin on the div you're adding. You have access to that specific div, because it's the one you're appending to the DOM. So if you have something like:
newDiv = $("<div>new stuff</div");
divContainer.append(newDiv);
newDiv.select2({...});
Clearly, you need to alter the above to fit the code you've got. If you need to run the plugin on some child elements of the new div, then you'd use something like:
newDiv.find("relevant child selector").select2({...});

DynaTree Syntax Error in onLazyRead

I haven't touched Javascript in years. So I am reacquainting myself with it and am basically a newbie again.
I am using Dynatree in a Django application. I can load the first two levels of the tree with the initial call to Django. However, when I add the onLazyRead function I get a syntax error:
SyntaxError: missing ; before statement
The entire script:
<script type="text/javascript">
$(document).ready((function(){
// Initialize the tree in the onload event
$("#prjtree").dynatree({
title: "Projects",
initAjax: {url: "/get_prjtree/",
data: {key: "root", // Optional arguments to append to the url
mode: "all"
}
},
onLazyRead: function(node) {
node.appendAjax({url: "/get_pcttree/",
data: {key: node.data.key, // Optional arguments to append to the url
mode: "all"
}
});
},
onActivate: function(node) {
alert("You activated " + node);
},
}); // end DynaTree
}));
</script>
The error is on the line:
node.appendAjax: {url: "/get_pcttree/",
I even tried rearranging the order of the functions.
If I comment out the entire onLazyRead function, it works as expected.
I just can't see where the problem is. I have compared it to several examples and it seems to be exactly like them. What am I missing?
Maybe typo error in:
node.appendAjax: { , shouldnt it be node.appendAjax({ ?

Set bootstrap tooltip to AJAX call results

I have a bootstrap tooltip that I want to load data from an AJAX requestion, with the text from the request being the titleproperty of the tooltip. My AJAX request works fine, but I have two problems:
Why isn't the data from the AJAX call making its way into the tooltip?
How can I use my ttManager object to encapsulate the tooltip's state?
Currently, when the page first loads and I click on #btnSubmit in the console I see
success and the correct data from the console.log(ttManager) line
$(document).ready(function () {
//this object's title attribute will be the value of ttManager.title seen below
var ttManager = {
title: '',
setTitle: function (data) {
this.title = data;
}
}
var ajaxCall = function () {
//this returns the top five results of text from a query
$.ajax({
type: "POST",
contentType: "application/json",
url: "Service.asmx/GetDrugs",
dataType: "json",
success: function (data) {
console.log('success');
ttManager.title = data.d;
//inside this function I want to set ttManager.title equal to the data.d
console.log(ttManager);
},
error: function (xhr) {
console.log('failed: ' + xhr.status);
}
});
}
$('#btnSubmit').tooltip({
//reference to ajax call
//title is the attribute responsible for displaying text in the tooltip
//I need to use a reusable object to set the text property instead of referencing ajaxCall
//would it be better if there below were title: ttManager.title?
title: ajaxCall,
trigger: 'click',
placement: 'right'
});
});
I'm pretty sure that I need a callback function somewhere, but I'm not sure where. Any future pointers would be appreciated, too. Thanks.
First, a little explanation of bootstrap's tooltip plugin. The tooltip displayed will pull from the elements title attribute if there's one present, otherwise it will use the title argument passed.
The next thing you need to understand is that ajax calls are asynchronous. This means code will continue to run while it's waiting for a response. So, for example, if I do something like this
$.ajax({
URL: 'google.com',
success: function(){
console.log('yay');
}
});
console.log('woohoo');
you'd see "woohoo" in the console before "yay". So, currently, you're calling $('#btnSubmit').tooltip before your ajax query has altered the state of ttManager.
The other issue is that you're currently not doing anything with ttManager in relation to bootstrap. I feel like I should also mention that the ttManager object seems meaningless here.
Personally, I would change my ajax success function to this (sets the title attribute, calls tooltip, then produces another click to make the tooltip appear)
success: function(data) {
$('#btnSubmit').attr('title', data.d)
.tooltip({
trigger: 'click',
placement: 'right'
}).click();
}
remove the current $('#btnSubmit').tooltip... code currently there, and add in a one time click handler to call your ajax.
$('#btnSubmit').one('click', function() {
ajaxCall();
});

JQGRID: Trigger Reload not working on iFrame

I have a web page with an iFrame. It loads a web page (same domain) with a jqGrid table. What I'm trying to do now is:
You press a link called search it opens a dialog with a filter form to filter your search.
When you press search button inside the dialog, it changes jqGrid url param and it should .trigger('reloadGrid').
It does all except the reloadGrid, I don't know why.
Any suggestion?
Code:
// DIALOG-ACTION-SEARCH IS THE BUTTON CLASS
$('#dialog').find('.dialog-action-search').button({icons: {
primary: 'ui-icon-search'
}, text: true}).click(function(e) {
e.preventDefault();
$('.content-center').contents().find('#list').setGridParam({
url: 'filteredsearch.html?option=1'
}).trigger('reloadGrid');
$('#dialog').dialog('destroy');
$('#dialog').remove();
});
setGridParam returns a jqGrid object, not a jQuery object, so I'm pretty sure you can't chain the trigger method. Try this instead:
var list = $('.content-center').contents().find('#list')
list.setGridParam({
url: 'filteredsearch.html?option=1'
})
list.trigger('reloadGrid');
I've found that before calling trigger('reloadGrid') with JSON data, you should reset the datatype parameter.
$("#grid").jqGrid('setGridParam', { datatype: 'json' });
In response to your comments, I would split up the chained method calls and then put a breakpoint on e.preventDefault() in Chrome debugger so you can assure that everything is actually getting hit.
$('#dialog').find('.dialog-action-search').button(
{
icons: { primary: 'ui-icon-search' } ,
text: true
});
$('#dialog').find('.dialog-action-search').click(function(e) {
e.preventDefault();
var grid = $('.content-center').contents().find('#list');
$(grid).jqGrid('setGridParam', { url: 'filteredsearch.html?option=1' });
$(grid).jqGrid('setGridParam', { datatype: 'json' });
$(grid).trigger('reloadGrid');
$("#dialog").dialog('destroy');
$("#dialog").remove();
});
While I'm a fan of chaining when you can, in this case I don't think you're going to find the root of the issues without doing things a little more explicitly, especially when using .find. How do you know that the .find is actually returning the element that you want?
I experienced same problem. I did not have time to investigate why it was happening but found a workaround for it.
In a javascript file that loads inside iframe with your grid I declared
window.top.reloadEventList = function () {
$("#grid").trigger("reloadGrid");};
Then just call
window.top.reloadEventList()
instead of
list.trigger('reloadGrid')

Categories