remove duplicate from React project - javascript

I'm using React as a front-end library for my rails project, I have been through an issue which is showing the errors for the user, I'm using Ajax to send request but I found my self duplicating error call back function if the server-side returns errors in every request inside every React.Component something like:
$.ajax({
url: URL,
type: METHOD,
data: {
//data
},
success: function () {
//calling some function
}.bind(this),
error(error) {
// begin
server_errors = JSON.parse(error.responseText);
array_of_keys_of_errors = Object.keys(server_errors);
for( i = 0 ; i < array_of_keys_of_errors.length; i++){
nested_keys = Object.keys(server_errors[array_of_keys_of_errors[i]]);
for( j = 0 ; j < nested_keys.length; j++){
array_of_errors = server_errors[array_of_keys_of_errors[i]][nested_keys[j]];
for( k = 0 ; k < array_of_errors.length; k++){
bootbox.alert({
message: nested_keys[j] + ' ' + array_of_errors[k],
closeButton: false,
});
}
}
}
// end
},
});
Is there an efficient way to keep my code away from redundancy, I was thinking about a shared file contains shared functions and include it inside each React.Component but I didn't find something similar to this.

You could create a function to handle your errors:
function handleErrors(errors) {
const server_errors = JSON.parse(error.responseText);
const array_of_keys_of_errors = Object.keys(server_errors);
for( i = 0 ; i < array_of_keys_of_errors.length; i++){
nested_keys = Object.keys(server_errors[array_of_keys_of_errors[i]]);
for( j = 0 ; j < nested_keys.length; j++){
array_of_errors = server_errors[array_of_keys_of_errors[i]][nested_keys[j]];
for( k = 0 ; k < array_of_errors.length; k++){
bootbox.alert({
message: nested_keys[j] + ' ' + array_of_errors[k],
closeButton: false,
});
}
}
}
}
And share that function across your files.
You would use it like this:
$.ajax({
url: URL,
type: METHOD,
data: {
//data
},
success: function () {
//calling some function
}.bind(this),
handleErrors
})

Related

get variable value in callback function

I have one callback function
function QueryKeyword(keyword, site, callback) {
var querykeyword = keyword;
var website = site;
$.ajax({
url: "http://www.test.com",
jsonp: "jsonp",
dataType: "jsonp",
data: {
Query: querykeyword
},
success: callback
});
}
I am calling this function with in for loop like this :
for (i = 0; i < questionTerm.length; i++) {
for (j = 0; j < site.length; j++) {
var searchTerm = questionTerm[i] + ' ' + $('#search').val();
QueryKeyword(searchTerm, site[j], function(reslt) {
// I need to get j variable value here
console.log(j);
});
}
}
Now I need to get "j" variable value in function see I console the j variable value but it does not get the j variable value.
Would you please let me know how I can fetch the value in this.
Thanks in advance
The problem is, that at the moment of your callback, j was reassigned multiple times to something different.
There are a few options you could do.
call your callback with the params you need
function QueryKeyword(keyword, site, index, callback) {
// ...
$.ajax(
success: function(result) {
// call the callback with a second param (the index j)
callback(result, index);
}
)
}
QueryKeyword(searchTerm, site[j], j, function(reslt, param) {
// param is j
console.log(result, param);
});
save the var in a closure
(function() {
var value = j;
...
})();
use forEach
questionTerm.forEach((term, i) => {
site.forEach((s, j) => {
// we are in a closure,
// j will be correct here.
QueryKeyword(term, s, function(reslt) {
// j is still correct here
console.log(j);
});
})
});
if you use es6, you could use let keyword. Here is some good explanation, how it works when using for loops
for(let i = 0; i < 10; i++) {
console.log(i);
setTimeout(function() {
console.log('The number is ' + i);
},1000);
}
You have to pass it in separately:
definition
function QueryKeyword(keyword, site, index, callback)
{
...
}
execution
QueryKeyword(searchTerm, site[j], j, function(reslt) {
// I need to get j variable value here
console.log(j);
});

Refresh & Clear JQuery Chosen plugin dynamically in ajax request

I am trying to dynamically populate the jquery chosen plugin both with "optgroup" and "option". I therefore have nested ajax requests and forloops:
$.ajax({
url: '#Html.Raw(Url.Action("GetCat", "MController"))',
data: { ID: metada },
success: function (data) {
var categories = data.split(",");
for (i = 0; i < categories.length; i++) {
$.ajax({
url: '#Html.Raw(Url.Action("GetCat", "MController"))',
data: { ID: cetada },
success: function (data) {
$("#picker").append("<optgroup label='" + categories[i] + "'>");
var subcategories = data.split(",");
for (i = 0; i < subcategories.length; i++) {
$("#picker").append("<option value='"+subcategories[i]+"'>" + subcategories[i] + "</option>")
}
$("#picker").append("</optgroup>");
}
});
}
$("#picker").trigger('chosen:updated');
}
});
Currently when I run the above the chosen select is empty and no options or optgroups are visible.
I think you need to use promises for this:
var promises = [];
for (var i = 0; i < categories.length; i++) {
promises.push(
(function(innerI){
return $.ajax({
url: '#Html.Raw(Url.Action("GetCat", "MController"))',
data: { ID: cetada },
success: function (data) {
var optgroup = $('<optgroup>').attr('label', categories[innerI]);
var subcategories = data.split(",");
for (var i = 0; i < subcategories.length; i++) {
var option = $('<option>').val(subcategories[i]).text(subcategories[i]);
optgroup.append(option);
}
$("#picker").append(optgroup);
}
});
})(i)); // unbind i to make closure work.
}
$.when.apply($, promises).then(function() {
$("#picker").trigger('chosen:updated');
});
UPDATE1:
I missed closures on first look, now th code is updated.
UPDATE2:
Rewrote working with tags inside success callback of ajax request.
UPDATE3:
Here is simple demo, I've commented some non-important code to show how it works.

Value won't push to array

In the code below, I assign a value to a variable from JSON with this var tag = data[j]['text']; and I output it with this console.log(tag); (for testing) which works.
I try to push the values into an array with tags.push(tag); but it WILL NOT WORK!
Why won't these values go into the array? I am just trying to get the contents of tag into an array...
function GetAvailableTags() {
var url = '/TextCodes/TextCodes?key=';
var tagGroups = [];
$('.ui-autocomplete-input').each(function () {
var key = $(this).attr('id');
var tags = [];
//console.log(key);
$.getJSON(url + key, function (data) {
for (var j = 0, len = data.length; j < len; j++) {
var tag = data[j]['text'];
console.log(tag);
tags.push(tag);
}
});
console.log(tags.length);
for (var k = 0, len = tags.length; k < len; k++) {
console.log(tags[k]);
}
});
}
Thanks for your help.
Because $.getJSON is an asynchronous function. It means that your code
console.log(tags.length);
for (var k = 0, len = tags.length; k < len; k++) {
console.log(tags[k]);
}
will be executed before the $.getJSON callback function :
function () {
var key = $(this).attr('id');
var tags = [];
//console.log(key);
$.getJSON(url + key, function (data) {
for (var j = 0, len = data.length; j < len; j++) {
var tag = data[j]['text'];
console.log(tag);
tags.push(tag);
}
}
It is why your variable seems to be empty when look into in your code above, but how it is possible that the data are printed with console.log(tag); in the callback function.
Update
Here is an example of using $.ajax method instead of $.getJSON to specify that the data must be retrieved synchronously using the parameter asynch : false
By that way, the server call response (success callback) is mandatory to continue the process. The disadvantage of this non-standard way is that your web page could be freezed waiting the server response. It is not the best elegant way to do that, but sometimes it is useful.
function GetAvailableTags() {
var url = '/TextCodes/TextCodes?key=';
var tagGroups = [];
$('.ui-autocomplete-input').each(function () {
var key = $(this).attr('id');
var tags = [];
//console.log(key);
$.ajax({
url: url + key,
type: 'POST',
asynch: false,//specify to stop JS execution waiting the server response
success: function (data) {
for (var j = 0, len = data.length; j < len; j++) {
var tag = data[j]['text'];
console.log(tag);
tags.push(tag);
}
},
error : function(jqXHR, textStatus, errorThrown) {
alert('an error occurred!');
}
});
console.log(tags.length);
for (var k = 0, len = tags.length; k < len; k++) {
console.log(tags[k]);
}
});
}
My solution is kind of long and stupid, but it works. Now, I can access the variables like an array textCodes['taxes']. sdespont's async note helped, too.
var textCodes = GenerateTextCodes();
console.log(textCodes);
function GenerateTextCodes() {
var arr = [];
$('.ui-autocomplete-input').each(function () {
var id = $(this).attr('id');
arr[id] = GetAvailableTags(id);
});
//console.log(arr['taxes']);
return arr;
}
// get all autocomplete element IDs and put them into an array
function GetAvailableTags(key) {
var url = '/TextCodes/TextCodes?key=';
var tags = [];
$.ajax({
url: url + key,
type: 'GET',
async: false,
success: function (data) {
//console.log(data[0].text);
//console.log(data.length);
for (var i = 0; i < data.length; i++) {
//console.log(data[i].text);
tags.push(data[i].text);
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert('an error occurred!');
}
});
//console.log(tags);
return tags;
}

jQuery: write variable between 2 quotation mark

I want to create a loop for input so that the variable img get number 1 to 5 like this:
img1, img2 ... img5.
How to write $i after img?
for ($i=1;$i<=5;$i++) {
function(data) { $('input[name="img1"]').val(data) });
}
Note: img is between two quotation mark.
it's edite:
user = $('input[name="name"]').val();
for (var i = 1; i <= 5; i++) {
$.post("test.php", { name: user, num: i },
function(data) {
$('input[name="img'+i+'"]').val(data)
});
}
The function you have declared in your loop seems weird. That's not valid javascript. You may try the following:
for (var i = 1; i <= 5; i++) {
$('input[name="img' + i + '"]').val(data);
}
or if we suppose that you have defined some function:
var foo = function(data, index) {
$('input[name="img' + index + '"]').val(data);
}
you could invoke it like this:
for (var i = 1; i <= 5; i++) {
foo('some data ' + i, i);
}
UPDATE:
An interesting example was provided in the comments section:
for (var i = 1; i <= 5; i++) {
$.post(
"test.php",
{ name: username, num: i },
function(data) {
$('input[name="img'+i+'"]').val(data);
}
);
}
This won't work because the i variable might have changed value between the loop and the AJAX success callback. To fix this you may try the following:
for (var i = 1; i <= 5; i++) {
(function(index) {
$.post(
"test.php",
{ name: username, num: index },
function(data) {
$('input[name="img'+index+'"]').val(data);
}
);
})(i);
}
or use the $.ajax() method which allows you to pass a context to the success callback:
for (var i = 1; i <= 5; i++) {
$.ajax({
url: 'test.php',
type: 'POST',
data: { name: username, num: i },
context: i, // here we are defining the context
success: function(result) {
// since we have used the context parameter, this variable
// here will point to the value that i had when we initiated
// the AJAX request
$('input[name="img' + this + '"]').val(result);
}
});
}
Like this:
for ($i=1;$i<=5;$i++) {
function(data) { $('input[name="img' + $i + '"]').val(data) });
}
By the way, I'm guessing you'e coming from a PHP background, but in JavaScript it is not conventional to use $ for variable names (except sometimes for jQuery objects). So normally you'd write your code like this:
for (i=1;i<=5;i++) {
function(data) { $('input[name="img' + i + '"]').val(data) });
}

Looping through results in jQuery

I get stacked on a looping issue and couldn't get it.
for (var i = 0; i < count; i++) {
FB.api({
method: 'fql.query',
query: 'SELECT name FROM user WHERE uid=' + temparray[i]
}, function (response) {
for (var x = 0; x < count; x++) {
$("#divfather" + x).html(response[0].name);
}
});
}
The second loop is done through response[0].name which is the name of Facebook and showing me the same response for all divs.
I want only this second loop being done to the i variable.
How can I do it?
It's a little hard to understand what you want, but I assume you only want the i from the outer for loop.
You'll need to create a new variable scope in order to retain it.
for (var i = 0; i < count; i++) {
FB.api({
method: 'fql.query',
query: 'SELECT name FROM user WHERE uid=' + temparray[i]
}, (function( j ) { // <---- create a function...
// v---------...that returns a function...
return function (response) {
$("#divfather" + j ).html(response[0].name);
};
})( i ) // <------...and invoke it immediately, passing "i"
);
}
Here's the same thing, but using a named function, which I think is a little nicer.
function get_callback( j ) {
return function (response) {
$("#divfather" + j ).html(response[0].name);
};
}
for (var i = 0; i < count; i++) {
FB.api({
method: 'fql.query',
query: 'SELECT name FROM user WHERE uid=' + temparray[i]
}, get_callback( i ) );
}
Or personally, I'd place all the logic in the function instead of splitting it up.
function set_up_FB_api( j ) {
FB.api({
method: 'fql.query',
query: 'SELECT name FROM user WHERE uid=' + temparray[ j ]
}, function (response) {
$("#divfather" + j ).html(response[0].name);
});
}
for (var i = 0; i < count; i++) {
set_up_FB_api( i );
}
You have a scope issue sken boy.
You are using i in the outer loop and then redeclaring it in the inner loop.
Change the second loop to some other letter like x.

Categories

Resources