URL is updating but Ajax call still going to old one - javascript

I am editing someone else project and they have used a lot of DOM which I'm not familiar with.
First select box
<select name="task_projectid" id="task_projectid"
data-assigned-dropdown="assigned"
data-ajax--url="/feed/projects?ref=general"></select>
When user select project I'm using following to update the data-ajax--url in task_itemid
$(document).on('change', '#task_projectid', function() {
$('#task_itemid').attr('data-ajax--url', '/feed/items?ref=' + this.value);
});
here is task_itemid box
<select name="task_itemid" id="task_itemid"
data-assigned-dropdown="assigned"
data-ajax--url="/feed/items?ref=">
</select>
It's working and url on task_itemid changed to
/feed/items?ref=4
But the Ajax call still going to
/feed/items?ref=
Please help.
I found this
$(".js-select2-basic-search-modal").select2({
theme: "bootstrap",
width: null,
containerCssClass: ':all:',
minimumInputLength: 1,
minimumResultsForSearch: 1,
ajax: {
dataType: "json",
type: "GET",
data: function (params) {
var queryParameters = {
term: params.term
}
return queryParameters;
},
processResults: function (data) {
return {
results: $.map(data, function (item) {
return {
text: item.value,
id: item.id
}
})
};
}
}
});

See the documentation:
It is recommended that you declare your configuration options by passing in an object when initializing Select2. However, you may also define your configuration options by using the HTML5 data-* attributes, which will override any options set when initializing Select2 and any defaults.
You're changing the attribute, but by that time Select2 has already been initialised and read the old value.
I think you can use the dynamic urls feature to read the value when the Ajax request is triggered.
ajax: {
url: () => $('#task_itemid').attr('data-ajax--url'),
I haven't tested this, and it might override the logic for adding a query string to the URL, in which case you'll need to make that function add the data from params.term too.

Related

How to analyze JS Literals/Identifiers using ESLint Custom Rules

I'll explain the scenario with an example.
Suppose I have following JS code:
$.ajax({
url: '/Department/GetAllUsers',
type: "POST",
data: data,
success: function (result) {
//Some Code
},
error: function () {
//Some Code
}
});
And I want to restrict call to that action of the controller. So I have written following Custom ES Lint rule for this:
module.exports = {
meta: {
type: "problem",
docs: {
description: "Prohibited Method",
category: "Method",
recommended: true,
url: ""
},
messages: {
messageDefault: "This method is Prohibited to use"
},
fixable: "code",
schema: [] // no options
},
create: function (context) {
return {
Literal(node) {
var literalValue = node.value.toString();
var cont = literalValue.split("/").filter(x => x.length > 1);
{
if (cont[0] === 'Department' && cont[1] === 'GetAllUsers') {
context.report({
node: node,
messageId: "messageDefault",
});
}
}
}
};
}
};
So here I am restricting use of 'Department/GetAllUsers' which is working great. The problem arises when I split the string or assign the string to a variable. For example
var controller = "Department";
var action = "GetAllUsers";
$.ajax({
url: "/" + controller + "/" + action,
//or '/Department/' + 'GetAllUsers'
type: "POST",
data: data,
success: function (result) {
//Some Code
},
error: function () {
//Some Code
}
});
Here the restriction does not work, is there a way in which I can resolve the variable values at the url? Is this even possible using ESLint?
In short I want something like the context.SemanticModel.GetSymbolInfo(node) which is used in Roslyn for C# code analysis.
Thanks
You can use ESLint's scope manager
https://eslint.org/docs/developer-guide/scope-manager-interface
There are many examples of using the scope manager in ESLint's own codebase:
https://github.com/eslint/eslint/search?q=getScope
Using this API you can follow the variable reference and inspect its assignments.
Note that this has some limitations. For example you won't be able to track values across module boundaries or function boundaries.

setDeleteFileParams doesnt seem to work

I am using 5.3.2 in basic mode as I need control over the UI.
I have added code to allow the uploads and then created little UI elements that can then trigger a deletion. I need to know the filename when I am deleting. So I used setDeleteFileParams but nothing is attached to the request.
var uploader = new qq.FineUploaderBasic({
button: document.getElementById('btnUploadFiles'),
debug: true,
autoUpload: true,
request: {
paramsInBody: true,
endpoint: '../myendpoint.htm',
params: {
tempID: 'myidwhatever'
}
},
deleteFile: {
enabled: true,
forceConfirm: false,
method: 'POST',
endpoint: '../myendpoint.htm'
},
callbacks: {
onSubmitted: function(id, name){
//do work
},
onDelete: function(id) {
this.setDeleteFileParams({filename: this.getName(id)}, id);
},
onDeleteComplete: function(UID, xhr, isError){
//remove my UI element
},
onComplete: function(UID, name, responseJSON, xhr) {
//create an element and stick it in
}
}
})
//ADD THE DELETE BUTTON ACTIONS
$('uploadedFiles').addEvent("click:relay(.deleteMyFile)", function(event, element) {
event.preventDefault();
arr = element.id.split('_')
uploader.deleteFile(arr[1]);
});
Im using Mootools as my JS framework. Everything triggers ok and the console logs out the filename correctly when I delete a file but when I look at the request there is no 'filename' parameter.
Thanks for any help.
By the time your onDeleteFile callback has been called, the file is already setup to be deleted. If you'd like to influence (or prevent) the underlying request, you'll need to put your logic inside of a onSubmitDelete callback handler instead.
For example:
callbacks: {
onSubmitDelete: function(id) {
console.log(this.getName(id));
this.setDeleteFileParams({filename: this.getName(id)}, id);
}
}

Typeahead.js include dynamic variable in remote url

I have tried for hours now, to get a variable in my "remote" path. The variable will change, depending on another input. Here is the code:
school_value = $('#school').val();
$('#school').change(function () {
school_value = $(this).val();
$('#programme').typeahead('destroy'); // I have also tried with destroy - but it doesnt work.
});
$('#programme').typeahead({
remote: 'typeahead.php?programme&type=1&school_name=' + school_value,
cache: false,
limit: 10
});
The variable 'school_type' is not set in the remote addr, and therefore not called.
Do you have any clue how to get it working? I have just switched from Bootstrap 2.3 to 3, and then noticed typeahead was deprecated. Above code worked on Bootstrap 2.3, but it seems like when the script is initialized, the remote path is locked.
I have found the solution! Code:
$('#programme').typeahead({
remote: {
url: 'typeahead.php?programme&type=1&school_name=',
replace: function () {
var q = 'typeahead.php?programme&type=1&school_name=';
if ($('#school').val()) {
q += encodeURIComponent($('#school').val());
}
return q;
}
},
cache: false,
limit: 10
});
Based on this threads answer: Bootstrap 3 typeahead.js - remote url attributes
See function "replace" in the typeahead.js docs
I believe the accepted answer is now out of date. The remote option no longer has replace. Instead you should use prepare:
$('#programme').typeahead({
remote: {
url: 'typeahead.php?programme&type=1&school_name=',
prepare: function (query, settings) {
settings.url += encodeURIComponent($('#school').val());
return settings;
}
}
});
One issue I ran into was pulling the value from another typeahead object. Typeahead essentially duplicates your input, including all classes, so you have two nearly identical objects, one with the tt-hint class and the other with tt-input. I had to specify that it was the tt-input selector, otherwise the value I got was an empty string.
$('.field-make').val(); // was "" even though the field had a value
$('.field-make.tt-input').val(); // gave the correct value
Bloodhound remote options
There is actually a slight refinement of Mattias' answer available in the newer Bloodhound js, which reduces duplication and opportunity for error:
$('#programme').typeahead({
remote: {
url: 'typeahead.php?programme&type=1&school_name=',
replace: function (url, query) {
if ($('#school').val()) {
url += encodeURIComponent($('#school').val());
}
return url;
}
},
cache: false,
limit: 10
});
#Mattias, Just as a heads up, you could clean up your replace method a little by supplying the optional url parameter.
$('#programme').typeahead({
remote: {
url: 'typeahead.php?programme&type=1&school_name=',
replace: function (url, query) {
// This 'if' statement is only necessary if there's a chance that the input might not exist.
if ($('#school').val()) {
url += encodeURIComponent(('#school').val());
}
return url;
}
},
cache: false,
limit: 10
});
Am I looking at the same thing as all of you?
http://www.runningcoder.org/jquerytypeahead/
It looks like it has changed AGAIN! It is not very obvious how to do it in the documentation, but there is example code. I pulled this straight from the code in the documentation.
There is a second example in the documentation where they do it yet a different way! This way is the most succinct I think.
// Set a function that return a request object to have "dynamic" conditions
dynamic: true,
source: {
tag: {
ajax: function (query) {
if (query === "hey") {
query = "hi"
}
return {
url: "http://www.gamer-hub.com/tag/list.json",
dataType: "jsonp",
path: data,
data: {
q: query
}
}
}
}
}
And here is my working example:
source: {
ajax: function() {
var filter = {
partnerId: #Model.PartnerId,
productTypeId: #Model.ProductTypeId,
unitType: $("[name=UnitType]").val(),
manufacturer: "",
columnName: "#nameof(SaleViewModel.Manufacturer)"
};
var queryString = $.param(filter);
return {
url: recentEntriesBaseUrl + "?" + queryString
}
}
},
If you want to use wildcard parameter %QUERY, then add url = url.replace("%QUERY", q);
$('#programme').typeahead({
remote: {
url: 'typeahead.php?programme&q=%QUERY',
replace: function (url, q) {
url = url.replace("%QUERY", q);
let val = $('#school').val();
if(val) url += '&school_name=' + encodeURIComponent(val);
return url;
}
},
limit: 10
});

Using select2: When using transport-function, results are not selectable

I am using the select2 plugin and I need to to use the transport-function to perform the ajax request on my own, because I need to set API Keys in the request-header. But as soon as I do this, select2 responses the results correctly and also formats and displays it like I want, but the results shown are not selectable. I can neither click at them, nor navigate to them with the arrow-keys, nor is there any mouseover effect when I go over them with the mouse.
Here's some code (I want to show suggestions for usernames):
ajax: {
data: function (term, page) {
return {
Searchtext: term
};
},
transport: function(queryParams){
// Api.Ajax delivers { Ajax: *the $.ajax object*, RequestId: *some requestId* }
var req = Api.Ajax("/api/suggestion/share/" + queryParams.data.Searchtext, "POST", { UserOnly: true }, queryParams.success);
return req.Ajax;
},
// parse the results into the format expected by Select2.
results: function(resp, page) {
return {
results: resp.Data,
more: false
};
}
},
Like I said, as soon as I use my own Ajax-function by implementing the transport-function, the results in the dropdown list are all shown, but not selectable.
Is this a bug, or am I doing something wrong?
#thnew This Answer will show you how to set request headers without requiring the transport function.

Backbone - Declare Default Parameters for a Fetch inside a Model

I have some global parameters that I want to be sent in every time I call a fetch on a collection... my issue is I don't want to declare the data: { ... } every time I fetch.
Is there a way I can provide default parameters inside the Collection itself with the possibility to add more or override some?
For example:
Instead of doing this every time:
this.articlesCollection.fetch({
dataType: 'jsonp',
data: {
deviceType: GlobalVars.deviceType,
memberId: GlobalVars.memberId,
authToken: GlobalVars.authToken,
targetObjectId: userId,
limit: 50,
excludeArticleBodies: true,
excludeViewedItems: false
},
success: function() {
_this.render();
}
});
I'd like to just provide a one or two parameters and a success function, like this:
this.articlesCollection.fetch({
data: {
targetObjectId: userId
},
success: function() {
_this.render();
}
});
... and have the Collection look something like:
define([
'underscore',
'backbone',
'global',
'utilities',
'models/article/ArticleModel'
], function(_, Backbone, GlobalVars, Utils, ArticleModel){
var ArticlesCollection = Backbone.Collection.extend({
model: ArticleModel,
initialize : function(view) {
this.view = view;
},
dataType: 'jsonp',
data: {
deviceType: GlobalVars.deviceType,
memberId: GlobalVars.memberId,
authToken: GlobalVars.authToken,
limit: 50,
excludeArticleBodies: true,
excludeViewedItems: false
},
url : function() {
return GlobalVars.baseAPIUrl + '/API/GetArticles';
},
parse : function(data) {
return data.Articles;
}
});
return ArticlesCollection;
});
Here's a working jsFiddle with one approach: http://jsfiddle.net/LEuGq/1/
Basically, you configure both an object of defaultParams and params as properties of your collection, which are used to dynamically compute the correct URL when fetch() is called. This way is probably more in alignment with backbone than changing the API of fetch() to accept parameters, which it is not designed to do.
var ParamCollection = Backbone.Collection.extend({
defaultParams: {deviceType: 'raceCar', limit: 42},
params: {},
url: function() {
return "/paramcollection?" + $.param(_.defaults(this.params, this.defaultParams));
}
});
var paramCollection = new ParamCollection();
paramCollection.params.excludeArticleBodies = true;
paramCollection.params.limit = 52;
$("#debug").append(paramCollection.url());
Backbone uses jQuery's ajax call by default, so you can set up anything you need as a default using various methods. See this question for some examples: jQuery's ajaxSetup - I would like to add default data for GET requests only

Categories