setState in $.get - javascript

When this.setState() is used within the $.get scope I get the following error
Uncaught TypeError: undefined is not a function
It works fine outside the $.get scope.
How can I fix this?
$.get(APIURL, function (data) {
this.setState({resdata: "This is a new state"});
});
I'm not sure what is the best practice to replace jQuery AJAX to other small AJAX libraries.

You can save a reference to the outer this:
var that = this;
$.get(APIURL, function (data) {
that.setState({resdata: "This is a new state"});
});
Or use $.proxy:
$.get(APIURL, $.proxy(function (data) {
this.setState({resdata: "This is a new state"});
}, this));
The this you use inside the function normally refers to the jqXHR object, ref http://api.jquery.com/jquery.ajax/

You can use bind(this) either, like in the React Documentation:
https://facebook.github.io/react/tips/initial-ajax.html
Here's a snippet of code:
componentDidMount: function() {
this.serverRequest = $.get(this.props.source, function (result) {
var lastGist = result[0];
this.setState({
username: lastGist.owner.login,
lastGistUrl: lastGist.html_url
});
}.bind(this));
},

Related

How to modify the response data of a jQuery AJAX call and return it as the updated jqXHR result?

I am using jsGrid whose loadData controller expects the data in an ajax call like:
controller: {
loadData: function() {
return $.getJSON(url).done(function(data) {
console.log(data)
});
},
//...definition for others insertItem, updateItem, deleteItem
}
The above works just fine.
I now need to massage data before passing them along to jsGrid. I suppose I have to do it inside the done function. How do I return the modified data?
You cannot return anything from an asynchronous function.
To do what you need you reverse your logic; make the AJAX request to get the data first, then use it to initialise the jsGrid within the callback handler. Something like this:
$.getJSON(url).done(function(data) {
var modifiedData = /* modify your data object/array here... */
$('#element').jsGrid({
data: modifiedData
});
});
Use the overload of the success callback with the jqXHR parameter:
controller: {
loadData: function() {
return $.getJSON(url).done(function(data,status,jqXHR) {
console.log(data)
//modify data and update it into jqXHR.responseJSON
console.log(jqXHR.responseJSON)
});
},
//...definition for others insertItem, updateItem, deleteItem
}

Issues with $.ajax, $.when and apply

I am having an issue with $.ajax, $.when and apply. I have a constructor:
The ajax request is not triggered when it should be :
http://plnkr.co/edit/Ul9d8tB7BHoZyHzzQQyB?p=preview
(see the console)
function updateGeneralTerm() {
return {
id: "GeneralCondition",
ajax: function () {
return $.ajax({
type: 'POST',
url: "#Url.Action("UpdateGeneralTerms", "Agreements")",
data: $("#GeneralConditions").serialize()
})
}
}
}
//I inject it in my custom function
function CustomFunction(arr) {
let arrOfAjax = arr.map(function (obj) {
return obj.ajax
});
$.when.apply(null, arrOfAjax);
}
CustomFunction([new updateGeneralTerm()];
In my CustomFunction, I am checking other stuff, as does the form has changed... etc. However it doesn't seem to be relevant for my issue. Nothing happens.
In the future I might have n specific term that I'd like to update only if forms has changed.
My issue: ajax are not requested by $.when(). If I am changing to return obj.ajax(), the ajax request is triggered there directly not by the $.when().
I 'd like the $.when() to handle all ajax requests.
http://plnkr.co/edit/Ul9d8tB7BHoZyHzzQQyB?p=preview
try to rewrite your CustomFunction function to use spread operator:
function CustomFunction(arr) {
let arrOfAjax = arr.map(function (obj) {
return obj.ajax
});
$.when(...arrOfAjax).then(function(...results) {
console.log(results);
});
}

How do I get a plain array back from vuejs with a component?

I am using a call to my database to retrieve some results and pushing them onto an array. However when I console.log(this.activeBeers) I don't get an array back but instead an object. How can I get a plain array back instead of a object?
Vue.component('beers', {
template: '#beers-template',
data: function() {
return {
activeBeers: []
}
},
ready: function() {
function getActiveBeers(array, ajax) {
ajax.get('/getbeers/' + $('input#bar-id').val()).then(function (response) {
$.each(response.data, function(key, value) {
array.push(value.id);
});
}, function (response) {
console.log('error getting beers from the pivot table');
});
return array;
}
console.log(this.activeBeers = getActiveBeers(this.activeBeers, this.$http));
},
props: ['beers']
});
AJAX is done asynchronously so you won't be able to just return the value that you do not have yet.
You should console.log your stuff after the $.each to see what you received.
As the other answers pointed out, your getActiveBeers() call is returning before the callback that fills the array gets executed.
The reason your array is an object is because Vue wraps/extends arrays in the underlying data so that it can intercept and react to any mutating methods - like push, pop, sort, etc.
You can log this.activeBeers at the beginning of your ready function to see that it's an object.
By the way, if you want to log the unwrapped/plain array of activeBeers, you can use your component's $log method:
this.$log(this.activeBeers);
The other answer is correct, getActiveBeers sends an HTTP request and then immediately returns the array, it doesn't wait for the ajax request to come back. You need to handle the updating of activeBeers in the success function of the ajax request. You can use the .bind() function to make sure that this in your success function refers to the Vue component, that way you can just push the ids directly into your activeBeers array.
Vue.component('beers', {
template: '#beers-template',
data: function() {
return {
activeBeers: []
}
},
ready: function() {
this.getActiveBeers();
},
methods: {
getActiveBeers: function(){
this.$http.get('/getbeers/' + $('input#bar-id').val()).then(function (response) {
$.each(response.data, function(key, value) {
this.activeBeers.push(value.id);
}.bind(this));
console.log(this.activeBeers);
}.bind(this), function (response) {
console.log('error getting beers from the pivot table');
});
}
}
props: ['beers']
});

JavaScript this scope in callback functions

How can I access object properties from functions which will be called as callback function. Please see code below. How can I access config property from processData function which will called when data is received from the server in ajax call.
MyClass: {
config: {
name: "",
id: ""
},
loadData: function() {
MyApi.getData(
this.config,
this.processData, //sucess
this.failureHandler //failure
);
},
processData: function() {
// how to access config object here?
}
}
Probably you can create an anonymous handler function and use call or apply to pass the this scope to actual handler function but is there a better solution than that?

Why can I not use this.posts out side the success function?

Maybe I am not understanding scoping but in the following:
AisisWriter.Routers.Posts = Backbone.Router.extend({
writer_posts: null,
posts: null,
routes : {
'': 'index'
},
initialize: function() {
this.writer_posts = new AisisWriter.Collections.Posts();
},
index: function() {
var self = this;
this.writer_posts.fetch({
reset: true,
success: function(collection, response, options){
this.posts = collection;
console.log(this.posts);
}
});
console.log(self.posts)
}
});
inside the success: function(){} the this.posts console log has two posts in it. it looks like:
child {length: 1, models: Array[1], _byId: Object, constructor: function, model: function…}
But when I try and use this.posts out side the fetch call, it returns null. Why is that? Is this not scoped properly? or am I doing something wrong?
You are not being able to get access to your this.posts only because it is executed sooner than you get the response. You even don't have to save 'this' in the self variable. To check it just add in the initialize function this line:
this.listenTo(this.writer_posts, 'reset', this.test);
And then create test function:
test: function() { console.log(this.posts); }
As you will see collection is saved properly.
Since your fetch might take time to get into success promise the next line is getting executed sooner before that.
index: function() {
var self = this;
this.writer_posts.fetch({
reset: true,
success: function(collection, response, options){
//write your callback function inside the success
//self.afterSuccess(collection);
}
});
},
You can pass the parameters for the function and fetch it.
afterSuccess: function(collection) {
console.log("the collection has"+JSON.stringify(collection));
}

Categories