Loading JSON data with button click and textbox

So I’m learning javascript and I’m trying to create a movie database where a user enters a movie id in a textbox and clicks the "load a movie button" which loads information about the movie with that specific id.

I was given a json file which contains elements of a movie such as the id, a title, release date, etc. I’m having trouble adding a click handler to my movie request button that creates an XMLHttpRequest object and submits a "GET" request for a specific movie. If this request is successful, the response text available in my callback function will be a JSON string containing the movie‚Äôs information in the format below. So in the console it would print out:

{
  "Title": "Guardians of the Galaxy Vol. 2",
  "Year": "2017",
  "Rated": "PG-13",
  "Released": "05 May 2017",
  "Runtime": "136 min",
  "imdbID": "tt3896198",
  "Response": "True"
}

and it should just print the title and runtime as regular text in the loaded html page as that’s what I’m requesting in the javascript file.

This json file only contains 1 movie for simplicity, but my original json file will contain information for thousands of movies, so when I’m searching a specific movie id, it should only load information for the one movie instead of all the movies in the json file. So if I enter "tt3896198" in the textbox, this id should load the data for the movie "Guardians of the Galaxy Vol. 2" as this is the id that matches this movie, as shown in the json file.

I tried looking up how to print specific information from the json file using XMLHttpRequests and JSON parsing but the problem is the examples I see online are able to access the variables in their json file by doing something like "movie.title" because their variables are lowercase. All my variables in my JSON file appear to be uppercase, and I don’t think doing movie.Title is allowed.

Additionally, I was wondering how I would load a movie based on what id the user enters? There are 1000s of movies with unique ids, and I’m not sure how to load only one movie whose id matches the id entered in the textbox.

Right now my page just shows a textbox and a button, but the button doesn’t work. Any help would be appreciated, I’m having trouble mostly with just getting the data from the json file to show up on the console as well as the HTML page when I click the button. If anyone could help or guide me in getting the movie id element to work, that’d be appreciated too!!

movie.html:

<html>
    <head>
        <title>Movies page</title>
    </head>

    <body onload="init()">
        <div>
            <input type="text" placeholder="Search" name="textbox">
            <button type="button" id="retrieveMovies">Load a movie</button>
        </div>
        <br />
        <div id="moviediv">

        </div>

    <script src="movies.js"></script>
    </body>

</html>

movie.js:

let movies = [];

function init(){
    document.getElementById("retrieveMovies").onclick = loadMovies;
    loadMovies();
}

function loadMovies(){
    let xhttp = new XMLHttpRequest();

    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            let responseObject = JSON.parse(xhttp.responseText);
            movies = responseObject.results;
            render();
        }
    };

    xhttp.open("GET", "movie.json", true);
    xhttp.send();
}

function render(){
    let content = "";
    movies.forEach(movie =>{
        content += `
            <div>
                <p> Movie: ${movie.Title}</p>
                <br/>
                <p> Runtime: ${movie.Runtime}</p>
            </div>
        `
    })
    document.getElementById("moviediv").innerHTML = content;
}

movie.json:

{"Title":"Guardians of the Galaxy Vol. 2","Year":"2017","Rated":"PG-13","Released":"05 May 2017","Runtime":"136 min","imdbID":"tt3896198","Response":"True"}

9 thoughts on “Loading JSON data with button click and textbox”

  1. Make sure you load your movies.js file, prior to calling init. I would include the script in the <head> and immediately add the init event as a callback to the DOMContentLoaded event for the document.

    Note: should also use "kebob-case" vs "camelCase" for id and class selector names.

    index.html

    Wrap your inputs in a form and listen to the submit event. Make sure you can access your query term e.g. IMDb ID. I pre-loaded the "tt3896198" so that the initial fetch would filter based on it. If you remove the text, nothing is filtered. If there is a term, it will filter on that.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <title>Movies page</title>
        <script type="text/javascript" src="movies.js"></script>
        <script type="text/javascript">
          document.addEventListener('DOMContentLoaded', init);
        </script>
      </head>
      <body>
        <form name="movie-search" onsubmit="return false">
          <input type="text" id="query" name="query" placeholder="Search" value="tt3896198" />
          <button id="retrieve-movies">Load a movie</button>
        </form>
        <br />
        <div id="movie-div"></div>
      </body>
    </html>
    

    movies.js

    Load the movies using a fetch instead of an XMLHttpRequest. Listen to the form’s submit event and make sure to return false in the HTML, to avoid server-side submission/redirect. I would also store variables in a context data structure. This makes the code much easier to follow.

    const context = {
      movies: []
    };
    
    const init = () => {
      document.forms['movie-search'].addEventListener('submit', loadMovies);
      loadMovies();
    };
    
    const loadMovies = () => {
      fetch("movie.json")
          .then(response => response.json())
          .then(onLoad);
    };
    
    const onLoad = (movies) => {
      const query = document.querySelector('#query').value.trim();
      context.movies = query ? movies.filter(({ imdbID }) => imdbID === query) : movies;
      render();
    };
    
    const render = () => {
      document.querySelector("#movie-div").innerHTML =
          context.movies.map(renderMovie).join('');
    };
    
    const renderMovie = ({ Title, Runtime }) => `
      <div>
        <p> Movie: ${Title}</p>
        <br/>
        <p> Runtime: ${Runtime}</p>
      </div>
    `;
    

    movies.json

    This should be an array of objects.

    [
      {
        "Title": "Guardians of the Galaxy Vol. 2",
        "Year": "2017",
        "Rated": "PG-13",
        "Released": "05 May 2017",
        "Runtime": "136 min",
        "imdbID": "tt3896198",
        "Response": "True"
      }
    ]
    
    Reply

Leave a Comment