Sometimes JSON object called from an AJAX request will be missing the key/property of the value I want to display in a table. The problem is when a key is missing it causes a "TypeError: Cannot read property 'name' of undefined" to be logged in the console and breaks my code. I tried using a || statement but that didn't work. See code snippet below:
function getNextObject() {
$.ajax({
url: "http://scrapi.org/object/" + randomNum,
success: function(data) {
var timeline = data.timelineList[0].name || "not available";
var medium = data.medium;
var culture = data.culture;
var geo = data.geography;
var date = data.dateText;
var gallery = data.galleryLink;
var title = data.title;
var artist = data.primaryArtist.name || "not available";
var image = data.currentImage.imageUrl;
PrimaryArtist and timelineList are not always contained in the JSON object throwing an error and causing code to break. How can I overcome this?
The problem is that your code is trying to get the .name of these variables and the variables themselves are probably empty.
You could build an if around the variables timelineList and primaryArtist
How about you try these replacements:
var timeline = data.timelineList ? data.timelineList[0].name : "not available";
...
var artist = data.primaryArtist ? data.primaryArtist.name : "not available";
Related
I am running parse server in NodeJS environment with express.
Generally, Parse automatically figures out which data has changed so only “dirty” fields will be sent to the Parse Cloud. So, I don’t need to worry about squashing data that I didn’t intend to update.
But why this following code is saving new data every time instead of updating the existing document data with name "Some Name".
// Parse code
Parse.initialize(keys.parseAppID);
Parse.serverURL = keys.parseServerURL;
var GameScore = Parse.Object.extend("GameScore");
var gameScore = new GameScore();
let data = {
playerName: "Some Name",
score: 2918,
cheatMode: true
};
gameScore.save(data, {
success: (gameScore) => {
// let q = new Parse.Query("GameScore");
// q.get(gameScore.id)
console.log("ID: " + gameScore.id)
},
error: function (gameScore, error) {
// Execute any logic that should take place if the save fails.
// error is a Parse.Error with an error code and message.
alert('Failed to create new object, with error code: ' + error.message);
}
});
// End of Parse code
The problem is that you're executing the query to find which object you want to update, but then you're not using the results when you go to save data.
query.first({ // This will result in just one object returned
success: (result) => {
// Check to make sure a result exists
if (result) {
result.save(data, {
// Rest of code
Note: You're treating playerName as a unique key. If multiple users can have the same playerName attribute, then there will be bugs. You can use id instead which is guaranteed to be unique. If you use id instead, you can utilize Parse.Query.get
Edit:
Since you want to update an existing object, you must specify its id.
var GameScore = Parse.Object.extend("GameScore");
var gameScore = new GameScore();
gameScore.id = "ID"; // This id should be the id of the object you want to update
I will design a a sample. My project will take all json data and insert to my web sql database.Firstly I used ajax for take my data and tried parse it. When I parsed , I dont access my json fields.
var oModel = new sap.ui.model.json.JSONModel();
var aData = jQuery
.ajax({
url : "http://../DataSource?format=json&key....",
dataType : "json",
success : function(data, textStatus, jqXHR) {
var JsonData = data;
oModel.setData(JsonData);
},
error : function(jqXHR, textStatus, errorThrown) {
}
});
obj = JSON.parse(oModel);
var myTextField = obj.Name;// This is not working
console.log(myTextField);
Also ı tried this.
var model = new sap.ui.model.json.JSONModel();
model.loadData("http://.../DataSource?format=json&key=...");
obj = JSON.parse(model);
var myTextField = obj.Name;
console.log(myTextField);
This my database. I want insert all name and surname field.
function populateDB(tx) {
tx.executeSql('DROP TABLE IF EXISTS emre');
tx.executeSql('CREATE TABLE IF NOT EXISTS emre (id unique, data)');
tx.executeSql('INSERT INTO emre (id, data) VALUES (?,?)', [ name ,
surname ]);
}
You seem to try parsing the model, but that is not a JSON structure but a UI5 object which happen to contain the JSON structure.
But why would you parse the JSON in the first olace?? If your AJAX call finishes successfully, and stores the retrieved data in your model, you can simply access it from the model using
model.getProperty("/path/to/your/property");
Have a look at the model API in the docs, there it is all well explained
EDIT to get to the data after it is loaded, use the attachRequestCompleted event handler:
var model = new sap.ui.model.json.JSONModel();
model.attachRequestCompleted( function(){
console.log(model.getProperty("Name"));
});
model.loadData("http:.../DataSource?format=json&key=...);
I am building a Chrome extension which should write new rows into a Google Spreadsheet. I manage to read the sheet content but am not able to write an additional row. Currently my error is "400 (Bad Request)". Any idea what I am doing wrong here?
I have gone through the Google Sheets API documentation and other posted questions here but was not able to find any solution.
Here is the code which I use to GET the sheet content (this works):
function loadSpreadsheet(token) {
var y = new XMLHttpRequest();
y.open('GET', 'https://spreadsheets.google.com/feeds/list/spreadsheet_id/default/private/values?access_token=' + token);
y.onload = function() {
console.log(y.response);
};
y.send();
}
And this is the code I try to POST a new row (gives me "400 - Bad Request"):
function appendRow(token){
function constructAtomXML(foo){
var atom = ["<?xml version='1.0' encoding='UTF-8'?>",
'<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gsx="http://schemas.google.com/spreadsheets/2006/extended">',//'--END_OF_PART\r\n',
'<gsx:name>',foo,'</gsx:name>',//'--END_OF_PART\r\n',
'</entry>'].join('');
return atom;
};
var params = {
'body': constructAtomXML("foo")
};
url = 'https://spreadsheets.google.com/feeds/list/spreadsheet_id/default/private/full?alt=json&access_token=' + token;
var z = new XMLHttpRequest();
z.open("POST", url, true);
z.setRequestHeader("Content-type", "application/atom+xml");
z.setRequestHeader("GData-Version", "3.0");
z.setRequestHeader("Authorization", 'Bearer '+ token);
z.onreadystatechange = function() {//Call a function when the state changes.
if(z.readyState == 4 && z.status == 200) {
alert(z.responseText);
}
}
z.send(params);
}
Note: spreadsheet_id is a placeholder for my actual sheet ID.
Follow the protocol and to make it work.
Assume spreadsheet ID is '1TCLgzG-AFsERoibIUOUUE8aNftoE7476TWYKqXQ0xb8'
First use the spreadsheet ID to retrieve list of worksheets:
GET https://spreadsheets.google.com/feeds/worksheets/1TCLgzG-AFsERoibIUOUUE8aNftoE7476TWYKqXQ0xb8/private/full?alt=json
There you can read list of worksheets and their IDs. Let use the first worksheet from the example. You'll find its id in feed > entry[0] > link array. Look for "rel" equal 'http://schemas.google.com/spreadsheets/2006#listfeed'.
In my example the URL for this worksheet is (Worksheet URL): https://spreadsheets.google.com/feeds/list/1TCLgzG-AFsERoibIUOUUE8aNftoE7476TWYKqXQ0xb8/ofs6ake/private/full
Now, to read its content use:
GET [Worksheet URL]?alt=json
Besides list-row feed, you'll also find a "post" URL which should be used to alter spreadsheet using list-row feed. It's the one where "rel" equals "http://schemas.google.com/g/2005#post" under feed > link.
It happens that it is the same URL as for GET request. In my case: https://spreadsheets.google.com/feeds/list/1TCLgzG-AFsERoibIUOUUE8aNftoE7476TWYKqXQ0xb8/ofs6ake/private/full. Just be sure to not append alt=json.
Now, to insert a new row using list-row feed you need to send POST with payload which is specified in docs. You need to send a column name prefixed with "gsx:" as a tag name. However it may not be the same as the column name in the spreadsheet. You need to remove any white-spaces, make it all lowercase and without any national characters. So to make your example work you need to replace <gsx:Name> with <gsx:name>.
Before the change you probably had the following payload message:
Blank rows cannot be written; use delete instead.
It's because the API didn't understand what the "Name" is and it just dropped this part of entry from the request. Without it there were no more items and the row was blank.
Alternatively you can read column names from the GET response. Keys from objects in feed > entry array that begins with gsk$ are columns definitions (everything after $ sign is a column name).
=================================================================
EDIT
To answer a question from the comments.
I've changed two things from your example:
function appendRow(token){
function constructAtomXML(foo){
var atom = ["<?xml version='1.0' encoding='UTF-8'?>",
'<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gsx="http://schemas.google.com/spreadsheets/2006/extended">',
'<gsx:name>',foo,'</gsx:name>',
'</entry>'].join('');
return atom;
};
/*
var params = {
'body': constructAtomXML("foo")
};
*/
var params = constructAtomXML("foo");
url = 'https://spreadsheets.google.com/feeds/list/'+spredsheetId+'/default/private/full?alt=json&access_token=' + token;
var z = new XMLHttpRequest();
z.open("POST", url, true);
z.setRequestHeader("Content-type", "application/atom+xml");
z.setRequestHeader("GData-Version", "3.0");
z.setRequestHeader("Authorization", 'Bearer '+ token);
z.onreadystatechange = function() {//Call a function when the state changes.
if(z.readyState == 4 && z.status == 200) {
alert(z.responseText);
}
}
z.send(params);
}
1) <gsx:Name> to <gsx:name>. Without it you'll receive an error.
2) params object should be a String! Not an object with some 'body' key. You just need to pass a value you want to send to the server.
Is there a way I can reference a list containing data from my database (item_list = inventory.objects.order_by('name')) in my jquery AJAX call?
This is my code:
/models.py:
class phonebook(models.Model):
name = models.Charfield(max_length=200)
phone_number = models.CharField(max_length=100)
/views.py:
def phonebook_home(request):
global phonebook
phonebook = phonebook.objects.order_by('name')
def get_next_3_contacts(request):
returnedContacts = phonebook[contactIndex:contactIndex+3]
return HttpResponse(phonebook)
/main.js:
var = ajax_call {
type: 'GET'
url: DEFINED_URL
data: {
index: contactIndex
},
dataType: 'html'
success: function (returned, textStatus_ignored, jqXHR_ignored) {
var contactIndex = 0
function phonebook_list(name, phone_number) {
"<li>" + name + " : " + phone_number + "</li>"
}
for(var index=0; index < 3; index++) {
var name = phonebook[index].name
var phone_number = phonebook[index].phone_number
$("ul").append(phonebook_list(name, phone_number))
}
contactIndex += 3
}
The phonebook[index].name / .phone_number returns "undefined" on my page. I want to keep my js file separate from my template file as it will be easier for me to debug, but unfortunately, this problem has stumped me. I also inputted an alert to test out if any data was being returned from the data base, which only returns a string containing the names of the contacts with no spacing in between contact names. Ex: "JaredSarahJohn".
All help and any bit of advice is appreciated!
A couple of things need to be cleaned up in order for this solution to work:
Your idea that global phonebook will be available from within get_next_3_contacts() is incorrect. When you make the AJAX call that will ultimately invoke get_next_3_contacts() the variable phonebook is no longer available. It went out of scope when the call to phonebook_home() completed.
What's the solution? Change phonebook_home() to accept an offset and count parameters. Have it hit the database and return the requested quantities. This is called pagination and is something you should get familiar with!
def phonebook_home(request, offset, count):
phonebook = phonebook.objects.all()[offset:offset+count]
But how do we get those results down to your AJAX handler? You can't just "return" a list of objects to the HTTPResponse() function - it's looking for text to render, not Model objects.
import json
from django.http import JsonResponse
def phonebook_home(request, offset, count):
status = "OK"
return_data = ""
try:
phonebook = phonebook.objects.all()[offset:offset+count]
return_data = json.dumps(phonebook)
exception:
status = "UH OH"
return JsonResponse({'data': return_data, 'status': status)
Is there a way I can find out all elements of a given name in teh form history. In my firefox addon, I am adding some elements in the form-history under a specific name - lest say "search-description".
I now want to get all the elements I added under this name. I see that I can get a history object :
this.Ci = Components.interfaces;
this.Cc = Components.classes;
var historyObj = this.Cc["#mozilla.org/satchel/form-history;1"].getService(this.Ci.nsIFormHistory2 || this.Ci.nsIFormHistory);
But the nsIFormHistory or nsIFormHistory2 interfaces do not have any function like:
getAllEntries(name)
Anyone can help me out in this?
Usually, nsIFormHistory2.DBConnection property is used for querying, you access the SQLite table directly. Something like this (untested):
var completionListener =
{
handleCompletion: function(reason) {},
handleError: function(error) {},
handleResult: function(result)
{
var values = [];
while (true)
{
var row = result.getNextRow();
if (!row)
break;
values.push(row.getResultByName("value"));
}
alert("Autocomplete values: " + values);
}
};
var query = "SELECT value " +
"FROM moz_formhistory " +
"WHERE fieldname='search-description'";
var statement = historyObj.DBConnection.createAsyncStatement(query);
historyObj.DBConnection.executeAsync([statement], 1, completionListener);
Note that using async API is recommended here, querying the database might take time.