Reputation: 327
I am learning vainilla JS (sorry in advance if I don't use some concepts properly), and while doing so, I am practising DOM manipulation and API fetching, with a free API i was given.
I have JSON with an structure similar to the one below, in which sometimes some fields get the value null
,or even change the structure of the attribute (as you can see in the 'Image Gallery' from the 3rd elelement.
I am looping through it to do different things, like creating a table, buidling some cards, and create an img gallery displaying the images from that element when clicking a button.
But whenever the loop finds the "null" value, it stops, and gives me a Cannot read property 'length' of null
The object is similar to this :
myObject = [
{
"field one": "something ",
"Image Gallery": [
{
"src": "anImage.jpg",
"title": "more text"
},
{
"src": null,
"title": "a title here"
},
{
"src": "otherImg.jpg",
"title": null
}
],
"Management": null,
"Scientific Name": "Urophycis tenuis",
"Species Illustration Photo": {
"src": null,
},
"last_update": "05/19/2021 - 13:04"
},
{
"Habitat Impacts": "something ",
"Image Gallery": null,
"Management": 'some value',
"Scientific Name": null,
"Species Illustration Photo": {
"src": 'img.jpg',
},
"last_update": "05/19/2021 - 13:04"
},
{
"Habitat Impacts": "something ",
"Image Gallery": // Note that the Image gallery structure is an array here
{
"src": "anImage.jpg",
"alt": "some text",
"title": "more text"
},
,
"Management": 'some value',
"Scientific Name": "Urophycis tenuis",
"Species Illustration Photo": {
"src": 'img.jpg',
},
"last_update": "05/19/2021 - 13:04"
}]
My Javascript code in which I get the error is :
function createCards(myObject) {
let cardContainer = document.getElementById('cardContainer');
for (let i = 0; i < myObject.length; i++) {
aInfoButtonLeft.onclick = function () {
for (let x = 0; x < myObject[i]["Image Gallery"].length; x++) {
console.log(myObject[i]['Image Gallery'][x]["src"])
}
}
}
}
How could I prevent the different "null" values to break the iteration, or to skip them and follow with the next value? The only way I can think of is to write if conditions, but I would need one per every kind of attribute which might contain a Null
Upvotes: 0
Views: 2658
Reputation: 8718
While most languages with loops have the break
statement, a good set of them also have the continue
statement, including JavaScript. This allows you to easily "skip" the current iteration:
for (let i = 1; i <= 4; i++) {
console.log('A' + i);
if (i%2 == 0) continue; // Only if a multiple of 2
console.log(' B' + i);
}
> A1
> B1
> A2
// no B2
> A3
> B3
> A4
// no B4
For your first problem, being dealing with null
values, you can simply check and continue. For your second problem, where the "Image Gallery"
has a different structure at times, there are a few options:
also I'm assuming that your code comment "Note that the Image gallery structure is a string here" meant to say that it's an array.
Showcasing both solutions at once, along with solving your first problem, we get something like this:
function createCards(myObject) {
let cardContainer = document.getElementById('cardContainer');
for (let i = 0; i < myObject.length; i++) {
let imgGallery = myObject[i]["Image Gallery"];
// For the first problem, ignore null values
if (imgGallery == null) continue;
/* - - - Example of 1st solution to 2nd problem (begin) - - - */
// Check whether imgGallery is an array (presumably of image objects)
if (Array.isArray(imgGallery)) {
// imgGallery is an array of images, iterate over it
for (const img of imgGallery) {
// handle img as an image
}
} else {
// imgGallery is already an image object
// handle imgGallery as an image
}
// The function would end here
/* - - - Example of 1st solution to 2nd problem (end) - - - - */
// 2nd solution for 2nd problem, we could force it to be an array
if (!Array.isArray(imgGallery))
imgGallery = [imgGallery];
// so we can just use the original code, except we now use
// the imgGallery variable of which we know it's an array
aInfoButtonLeft.onclick = function () {
for (let x = 0; x < imgGallery.length; x++) {
// I noticed the .src can still be null, which we want to skip?
// Mind that `continue`, just like `break`, works on the "closest" loop
if (imgGallery[x].src == null) continue;
console.log(imgGallery[x].src)
}
}
}
}
I noticed that image objects themselves can still have a src
that's null
. Adding another simple (if src == null) continue;
check is all you need, as shown in the updated code above.
Upvotes: 2
Reputation: 589
Onclick function should be outside of both of for loops.
p.s: Using the snippet makes things easier.
var myObject = [{
"field one": "something ",
"Image Gallery": [{
"src": "anImage.jpg",
"title": "more text"
},
{
"src": null,
"title": "a title here"
},
{
"src": "otherImg.jpg",
"title": null
}
],
"Management": null,
"Scientific Name": "Urophycis tenuis",
"Species Illustration Photo": {
"src": null,
},
"last_update": "05/19/2021 - 13:04"
},
{
"Habitat Impacts": "something ",
"Image Gallery": null,
"Management": 'some value',
"Scientific Name": null,
"Species Illustration Photo": {
"src": 'img.jpg',
},
"last_update": "05/19/2021 - 13:04"
},
{
"Habitat Impacts": "something ",
"Image Gallery": // Note that the Image gallery structure is a string here
{
"src": "anImage.jpg",
"alt": "some text",
"title": "more text"
},
"Management": 'some value',
"Scientific Name": "Urophycis tenuis",
"Species Illustration Photo": {
"src": 'img.jpg',
},
"last_update": "05/19/2021 - 13:04"
}
]
function createCards(myObject) {
let cardContainer = document.getElementById('cardContainer');
aInfoButtonLeft.onclick = function() {
for (let i = 0; i < myObject.length; i++) {
if (myObject[i]["Image Gallery"]) {
for (let x = 0; x < myObject[i]["Image Gallery"].length; x++) {
console.log(myObject[i]['Image Gallery'][x]["src"])
}
}
}
}
}
createCards(myObject)
<input id="aInfoButtonLeft" type="button" value="Button">
Upvotes: 0
Reputation: 480
As posters above have mentioned, you'd need to check whether the value is null. You simply can't loop through an object that doesn't exist! So your choice would be not to use null objects in your structure -I'm not quite sure why you need them in the first place, maybe you could have a structure you loop through and another, placeholder structure - OR to check for null.
Upvotes: 1
Reputation: 2293
Try with an if statement. It will catch null
and undefined
objects:
if (myObject[i]["Image Gallery"] != null) {
for (let x = 0; x < myObject[i]["Image Gallery"].length; x++) {
console.log(myObject[i]['Image Gallery'][x]["src"])
}
}
Upvotes: 2