0

Have looked at similar stack overflow answers, but can't figure this one out.

I'm making an API call, which definitely returns an object. When I loop through my data and inject this into the DOM, it appears as a string.

So when I go back to, JSON.parse(data) my data, it get return the following error:

Uncaught (in promise) SyntaxError: Unexpected token o in JSON at position 1

I know, this is because the data is already turned into a string, but I am not turning into a string anywhere.

Basically, I do not want my elem.largeImageURL to be injected as a string.

Here's my full JS code. Can't figure what i've done wrong?

function PixabayAPIService() {
const searchURL = 'https://pixabay.com/api/';
const apikey    = 'MY_API_KET';

function getImages(carouselContainer) {
  fetch(`${searchURL}?key=9656065-${apikey}&q=beautiful+landscape&image_type=photo&page=1&per_page=6`)
    .then((res) => {
      return res.json();
    })
    .then((data) => {
      console.log('data', data);   //HERE TYPEOF DATA IS OBJECT

      let result = '';
      data.hits.forEach(elem => {

        console.log(typeof elem.largeImageURL);  //HERE TYPEOF IS STRING
        result +=
                `<div class="item"><img src="${elem.largeImageURL}" /></div>`;
        carouselContainer.append(result);
      });
    });
}

return {
  getImages
};

}

Here's how my console.logs look:

app.js loaded
count 0

data {totalHits: 500, hits: Array(6), total: 
7781}hits: (6) [{…}, {…}, {…}, {…}, {…}, {…}]total: 7781totalHits: 
500__proto__: Object

object
string

And here is how the DOM is returned - template literals are injected as strings:

https://i.stack.imgur.com/oONF1.png

Reena Verma
  • 1,617
  • 2
  • 20
  • 47
  • 2
    you're trying to parse a string that probably says `[object Object]` - since `fetch` ... `res.json()` returns an **object** there's no need to JSON.parse it - however, the code you've shown does NOT include `JSON.parse(data)` - so how can the code you've shown produce that error? – Bravo Nov 02 '19 at 22:52
  • oh, and a `src` attribute MUST be a string ... what did you want it to be? it's a URL – Bravo Nov 02 '19 at 22:55
  • 1
    Why you want elem.largeImageURL be something else than string. I think should be a string. – Raúl Martín Nov 02 '19 at 22:56
  • @Bravo - exactly! I don't know why it's appearing, as I'm not passing anywhere.... I'm using template literals to inject a div. And each div, is injected into the DOM as an entire string. – Reena Verma Nov 02 '19 at 22:56
  • I'm not talking about elem.largeImageURL. This entire element is inject as a string: "
    "
    – Reena Verma Nov 02 '19 at 22:57
  • 2
    I see the problem ... `element.append(result)` ... read [documentation](https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/append) ... it doesn't work like jQuery – Bravo Nov 02 '19 at 22:57
  • I mean YOU WANT A STRING. Also result += `
    `; carouselContainer.append(result);` this looks wrong. probably you want `=` no `+=`
    – Raúl Martín Nov 02 '19 at 22:57
  • 1
    append() doesn´t expect a html string. It expects Dom Elements. e.g. you can create a div with document.createElement("div") Edit: As @Brav – user148397 Nov 02 '19 at 22:58
  • @RaúlMartín - The problem is in the consoles.... you can see, when you loop through the object, even before I use a template literal to inject into DOM, the object has been turned into a string. – Reena Verma Nov 02 '19 at 22:58
  • For more information please have a look at the documentation here: https://www.w3schools.com/jsref/met_document_createelement.asp – user148397 Nov 02 '19 at 22:59
  • https://stackoverflow.com/questions/6304453/javascript-append-html-to-container-element-without-innerhtml – ibrahim mahrir Nov 02 '19 at 22:59
  • can you write the console.log(result) here. – Raúl Martín Nov 02 '19 at 23:00
  • 1
    @ReenaVerma where did the "object turn into a string"? – ibrahim mahrir Nov 02 '19 at 23:00
  • @charlietfl ok, i'll try changing the append. thank you. – Reena Verma Nov 02 '19 at 23:00
  • There is @charlietfl https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/append – user148397 Nov 02 '19 at 23:01
  • so going back, change `result +=` by `result =` – Raúl Martín Nov 02 '19 at 23:03
  • `it's never turned from object to string` the thing is, result was never an object, it is always a string - so nothing has magically changed it to a string – Bravo Nov 02 '19 at 23:04
  • Notice that append accept DOMstrings too. – Raúl Martín Nov 02 '19 at 23:12

1 Answers1

1

when using element.append, it does accept a string, but it doesn't interpret that string as HTML - it just appends the string to the element as a text node

You'll want something like:

function PixabayAPIService() {
    const searchURL = 'https://pixabay.com/api/';
    const apikey = 'MY_API_KET';

    function getImages(carouselContainer) {
        fetch(`${searchURL}?key=9656065-${apikey}&q=beautiful+landscape&image_type=photo&page=1&per_page=6`)
        .then((res) => {
            return res.json();
        })
        .then((data) => {
            data.hits.forEach(elem => {
                // change from here
                let result = document.createElement('div');
                result.classList.add('item');
                result.innerHTML = `<img src="${elem.largeImageURL}" />`;
                // to here
                carouselContainer.append(result);
            });
        });
    }

    return {
        getImages
    };
}
Bravo
  • 6,022
  • 1
  • 10
  • 15
  • = thank you so much Bravo! I didn't realise append would mis-interpret in that way. Previously, I use innerHTML, which usually works fine. So why I didn't notice this. Thank you!!!!! – Reena Verma Nov 02 '19 at 23:08
  • `mis-interpret` - no, it's not mis-interpreting anything, it's how the function works :p – Bravo Nov 02 '19 at 23:12
  • Okie dokes - will remember this for sure haha :) – Reena Verma Nov 02 '19 at 23:23