here is my JavaScript code:
var Model =
{
get: function(id)
{
return this.data[id];
},
data: {},
init: function()
{
var self = this;
$.getJSON(urlToServer, function(data)
{
$.each(data, function(i, object)
{
self.data[object.id] = object;
console.log(object.id); // output is: 1, then 2, then 3
});
});
}
};
Model.init();
console.log(Model); // output is the initialized object with children objects 1, 2, 3
console.log(Model.get(1)); // output is undefined
As you can see from the console output i put in the comments, everything works fine until the last line of code. I define a Model and initialize it with some JSON objects provided by the server. But all of a sudden, when i try to access a single child object through the get() method, the Model appears to be undefined.
I just don't get it, please help me out.
Thanks.
Looking at the sample code you used, Model.get(1) will always return undefined.
$.getJSON is an AJAX call that does not necessarily return immediately (known as asynchronous). You will need to use the callback you supplied to $.getJSON to fire off any logic depending on Model.get(1), otherwise it will remain undefined.
$.getJSON is a asynchronous request, you must wait for the response before you call Model.get()
You trying to retrieve object's field "142". I guess you get from json only "1", "2" and "3" id's? If i'm right then get function return to you correct answer because no object field "142" exists.
Related
Is there any way I can obtain the data from a JSON file and save them into a multidimensional array in JavaScript.
The JSON file is a .php file with header set to JSON.
I've tried so far:
var questionJSONS="";
$(document).ready(function(){
var questionJ="";
$.getJSON("http://localhost:8080/audioMillionaire/test2.php",function(result){
$.each(result, function(i, item){
questionJ+= "['"+result[i].qid+"','"+result[i].description+"','"+result[i].a+"']";
});
setArray(questionJ);
});
});
And many other things, but none of them seem to work.
I think this is what you meant:
$(document).ready(function() {
var questions = [];
$.getJSON("http://localhost:8080/audioMillionaire/test2.php", function(result) {
$.each(result, function(i, item) {
questions.push([result[i].qid, result[i].description, result[i].a]);
});
});
});
If not, please comment.
Edit: BenM was faster
Edit:
This works as well, but I cannot use the array outside of $.getJSON
This is because you are probably using code like this:
...
questions.push([result[i].qid, result[i].description, result[i].a]);
});
});
console.log(questions);
Because javascript is an asynchronous language the console log call happens before the pushes after the json was requested. You can read more about it here.
$(document).ready(function() {
console.log("set test to old");
var test = "old";
setTimeout(function() {
console.log("set test to new");
test = "new";
console.log("inside timeout: " + test);
}, 3000); // runs in 3 seconds
console.log("outside timeout: " + test);
});
This code should provide a good example. The function setTimeout just waits 3 seconds and runs the function (much like the json request).
Knowing this you should find a solution on your own (like calling a passed function after the array has been pushed). If not comment.
Edit: changed link to other, better page.
In your example, questionJ is being treated as a string, and without seeing your setArray() function, it's difficult to say for sure what's wrong (I don't know if you're parsing the string inside this function, for example).
However, assuming that you wish for questionJ to be an array of arrays, the following should work:
questionJSONS = [ ];
$.getJSON('http://localhost:8080/audioMillionaire/test2.php', function(result){
$.each(result, function() {
questionJSONS.push( [ this.qid, this.description, this.a ] );
});
});
Notice that inside the $.each function, you can reference this, which refers to the currently iterated item. Using this method (with push() and the array data structure) directly, the datatype is also preserved from the JSON.
Also, since you're not directly interacting with the DOM inside of the snippet, there's no requirement to wrap it inside the DOMReady handler.
I have a static file that's just one date-time per line, e.g.:
2014-03-14T16:32
2014-03-15T13:04
2014-03-16T06:44
...
I want to use that as a read-only data source for a backbone collection. Obviously that's not in the expected format. I thought I could just use the parse method on my collection to just convert it into a proper array of objects. Unfortunately, that doesn't seem to be working.
First, if I don't override fetch, the parse method never gets called -- it goes into the error handler, though it's unlcear exactly why -- it's not actually throwing any errors. I'm guessing that's because it's expecting a different response type or something?
Second, if I override both the fetch & parse methods thus:
var MyColl = Backbone.Collection.extend({
model: MyModel,
url: 'date-list.txt',
parse: function(data) {
var result = _(data.split("\n")).compact().map(function(item, i) {
return { theDate: item, globalIndex: i };
});
return result;
},
fetch: function() {
$.get(this.url, this.parse);
}
});
it correctly goes into parse, and parse seems to build a valid object, but my collection has 0 models after the whole operation...
I suppose the collection is winding up empty because when I call parse, it's not part of the expected flow any more so nothing is done with the result. Any other ideas about how I can make fetch properly handle what the server is returning?
Obviously, I could make the server return JSON, or I could use my own fetching function outside of backbone, but I'm hoping there's a way to avoid those ideas.
I believe the default fetch method assumes you will be returning JSON from the endpoint, which the collection will then instantiate a new model for each object in the array from the JSON data.
With your current override, you just need to just build an array of Backbone models in your parse method:
parse: function(data) {
var model = this.model;
var result = _(data.split("\n")).compact().map(function(item, i) {
return new model({ theDate: item, globalIndex: i });
});
return result;
},
It looks like you are not passing correct function to $.get, or, to be more precise, correct function but not bound to specific object instance. One idea is to try this:
$.get(this.url, _.bind(this.parse, this));
But now, as you said, nothing is done with the result of parse method, so you can add elements to collection like this:
parse: function(data) {
var result = _(data.split("\n")).compact().map(function(item, i) {
return { theDate: item, globalIndex: i };
});
this.set(result);
}
I have the following code:
for (_field in _fields) {
$.post(
'/api/fields',
{ id: _field.id },
function(data, _field) {
alert(data);
} (data, _fields[_field)
);
}
I have to pass the _fields[_field] element to the function that returns the data from the jQuery because loses the reference to the right object during the loop. The problem is that in defining that the post function should have a _field parameter, you also have to specify a parameter for data, or data will be overwritten with _field.
Currently data returns as undefined because I have no data object defined inside the loop. I also tried passing in null, but that also just returns null. I'm looking for a way to pass the element without overwriting the data returned from the post function.
Is there any way to fix this, or is there perhaps an alternative jQuery method that can do what's needed?
You want a function factory function — a function that creates a function:
for (_fieldName in _fields) {
$.post('/api/fields',
{
// Unrelated, but I think this bit is wrong; shouldn't it be
// `id: _fields[_fieldName].id` ? You're trying to use `.id` on
// a string -- see below for a full update
id: _fieldName.id
},
makeHandler(_fields[_fieldName])
);
}
function makeHandler(field) {
return function(data) {
// Use `data` and `field` here
};
}
Note that in the object initializer we're passing into $.post, we're calling makeHandler to it runs and returns the function we'll then pass into $.post. That function is then called when the $.post completes, and has access to the data argument that $.post gives it as well as the field argument to makeHandler, because it's a closure over the context of the call to makeHandler, which includes the field argument. More: Closures are not complicated
Note that in the code above, I changed your variable _field to _fieldName to be more clear: The variable in for..in loops is a string, the name of a property. See also the comment, I think you were trying to use .id in the wrong place. Here's what I think you really wanted:
for (_fieldName in _fields) {
_field = _fields[_fieldName];
$.post('/api/fields',
{
id: _field.id
},
makeHandler(_field)
);
}
function makeHandler(field) {
return function(data) {
// Use `data` and `field` here
};
}
Also note that if _fields is an array, you shouldn't use for..in on it without safeguards. More: Myths and realities of for..in
var s = store.get('billablexxxx');
if (!s) {
if (false) {
s = {
"something" : 'Value', ....
}
}
}else {
s = new Object;
$.getJSON('Translation/GetIndexLabels', function(data) {
$.each(data, function(key, val) {
s[key] = val;
// temp[key] = val;
})}) ;
}
}
//here i use the variable
But where i use the variable, the dynamic properties dissapaered, it's not undefined but it's an empty object.
However, when it has been set in the $.getJSON() function, all values are added.
What did i do wrong?
Edit:
Fixed the problem by putting it into a function. When i posted the question, i was already close to the answer that i have looked for the last "hour" (weird javascript console results brought confusion).
Thanks for the advice!
The call to $.getJSON() is asynchronous, so the execution will reach the part where you "use the variable" before the asynchronous call completes.
The usual way to deal with this is to have the use of the variable inside a callback function that is referenced in the getJSON() call.
Here's the reference: http://api.jquery.com/jQuery.getJSON/
The getJSON method is asynchronous, it calls your function(data) once it has completed.
At the point which you are using s, the getJSON method has not yet returned so the properties of s have not been initialised.
Can someone tell me why this alert is empty?
var pending_dates = [];
$.getJSON('/ajax/event-json-output.php', function(data) {
$.each(data, function(key, val) {
pending_dates.push({'event_date' : val.event_date});
});
});
alert(pending_dates);
I can't get my head around this. Am I not declaring pending_dates as a global variable, accessible within the each loop? How would one solve this?
Please note that the JSON output is working well. If I would declare pending dates within the getJSON function (and alert within that function), it works, but I need to store the data in an array outside of that getJSON function.
Thanks for your contributions.
EDIT
Thanks to your comments this code is working:
pending_dates = [];
$.getJSON('/ajax/event-json-output.php', function(data) {
$.each(data, function(key, val) {
pending_dates.push({'event_date' : val.event_date});
});
}).success(function() { alert(pending_dates); })
Thanks a lot for your contributions!
I think the problem is $.getJSON is an asynchronous call - it returns immediately and then alert(pending_dates) is invoked.
However, when that happens, the response from the asynchronous call may not have been received, and hence pending_dates may not have been populated.
That is probably why it is empty at the time alert(pending_dates) is called.
Your alert is executing before the JSON call has finished. Remember this JSON it fetched and processed asynchronously, but your alert comes right after it's started. If you want an alert, then you need to put it at the completion of the getJSON call.
$.getJSON is working asynchronously meaning that whatever you have specified in the callback will be executed eventually but there is no guarantee that will happen by the time you reach alert('pending_dates').
You can verify this by moving alert('pending_dates') right after
pending_dates.push() (this would result in one alert being displayed for each item it is retrieving).
You can write a function to start working with the data you're retrieving as soon as it is available:
var pending_dates = [];
$.getJSON('/ajax/event-json-output.php', function(data) {
$.each(data, function(key, val) {
pending_dates.push({'event_date' : val.event_date});
doSomething(val.event_date);
});
});
function doSomething(date) {
// do something with date
// like writing it to the page
// or displaying an alert
}
With this you'll be able to work with all the data you get as it becomes available.
Variables are global by default in Javascript - having var actually introduces scope. Remove that and see if it helps.
It's more likely that the AJAX response isn't returning any data. Can you try pushing just 'foo' onto the array, and see if the alert shows anything different?