首页 > 解决方案 > How to display JSON data on click with JavaScript

问题描述

I'm having some trouble with writing the logic of this code. I've parsed data from this large api.

Code currently retrieves all program titles (there are multiple instances of the same title) and compares it with the late night show array, then prints them out once in their own <p> tag.

I'd like to somehow click a program title and display more JSON data.

I thought to compare the <p> innerHTML, to the title variable, and when its div is clicked, return the list of guests for that particular program. I've been playing with the logic, and not too sure if I'm on the right track.

var data = JSON.parse(request.responseText);
var set = new Set();
var x = '';
const lateNightHosts = ['The Late Show with Stephen Colbert', 'Conan', 'Jimmy Kimmel Live'];


class TVProgram {

constructor(title, guests) {
  this.title = title;
  this.guests = guests;
}

// Gets title instance once to display in view
getShow(array) {
  let programs = document.getElementById('programs');
  let elem = '';

  if (array.indexOf(this.title) !== -1){
    if (!set.has(this.title)) {
      set.add(this.title);
    }
    set.forEach((value) => {
      elem += cardTemplate(value)
    });
    programs.innerHTML = elem;
  }

  getLineup() { 
    // if div is clicked, get name in <p>
    // if name == title variable, print guests
  }
}

function cardTemplate(value) {
  return `
  <div class = "cards">
    <p class = "host">${value}</p>
  </div>
  `
}

//...
for (x in data){
  // JSON properties
  let title = data[x]._embedded.show.name;
  let guests = data[x].name;

  let latenight = new TVProgram(title, guests);
  latenight.getShow(lateNightHosts);
}

I'd like to stick to vanilla JavaScript. Relatively new to the language, thanks in advance!

标签: javascripthtmlarraysjsonget

解决方案


I've read what you wanted, and I came up with my own approach. You can see a working copy over here https://jsfiddle.net/sm42xj38/

const lateNightHosts = ['The Late Show with Stephen Colbert', 'Conan', 'Jimmy Kimmel Live'];


class TVProgram {

  constructor(data) {
    this.data = data;
    this.popup = this.popup.bind(this); // this is required because I'm setting this.popup as the callback for click
  }

  popup(){
    // Just a simple alert which pretty prints all the JSON data for this TVProgram
    alert(JSON.stringify(this.data, null, 10));
  }

  render(){
    const {name} = this.data;

    let card = document.createElement('div');
    card.className = "cards";
    let host = document.createElement('p');
    host.className = "host";
    // When the user clicks the element, the popup() function is called on this specific object. This specific object has the data for 1 TVProgram. 
    host.addEventListener('click', this.popup); 
    // above event could also be, then the binding in the constructor is not required.
    // host.addEventListener('click', function() { this.popup() }); 
    host.textContent = name;
    card.append(host);

    return card;
  }
}

// call the API
axios.get('https://api.tvmaze.com/schedule/full').then(response => {
    return response.data;
})
.then(data => {
  // filter the shows only available in the lateNightHosts list
  return data.filter(m => ~lateNightHosts.indexOf(m._embedded.show.name));
})
.then(shows => {
    // Create a TVProgram for each of the filtered shows
    return shows.map(show => new TVProgram(show));
})
.then(programs => {
    // Add every TVProgram to a DOM element
    programs.forEach(program => {
    document.getElementById("shows").appendChild(program.render());
  })

})

As you can see, I'm using axios as a http client, because it's less code.

It's VERY VERY loosely based on how React works, with a render method on the TVProgram class. I'm not using templates, because complexity of the template. The event is based on the dom element which is bound to the TVProgram which has only the data of that specific show. Therefor all data is stored in memory, and not in the DOM.


推荐阅读