Interact with a JSON API using JavaScript by incorporating dynamic user input

Recently, I delved into tutorials on utilizing JSON data and JavaScript. Feeling inspired, I decided to create a simple app using an API. However, I encountered a hurdle and I'm struggling to identify its cause. The problem seems to be related to how I manipulate user input to modify the query string.

const movies = [];
const endpoint = 'http://www.omdbapi.com/?apikey=myAPIkey=batman';

fetch(endpoint)
 .then(blob => blob.json())
 .then(data => movies.push(...data.Search));

When I switch to using a static endpoint without the 'movieSearch' function like above, everything works smoothly albeit statically.

Here is my current code:

  const movies = [];

  function movieSearch() {
    const replace = this.value;
    const endpoint = 'http://www.omdbapi.com/?apikey=myAPIkey=' + replace;

    movies.length = 0;

    fetch(endpoint)
      .then(blob => blob.json())
      .then(data => movies.push(...data.Search));
  }

  function findMatches(wordToMatch, movies) {
    return movies.filter(film => {
      const regex = new RegExp(wordToMatch, 'gi');
      return film.Title.match(regex) || film.Year.match(regex)
    })
  }

  function displayMatches() {
    const matchArray = findMatches(this.value, movies);
    const html = matchArray.map(film => {
      const regex = new RegExp(this.value, 'gi');
      const titleName = film.Title.replace(regex, `<span class="hl">${this.value}</span>`)
      const yearName = film.Year.replace(regex, `<span class="hl">${this.value}</span>`)
      return `
        <li>
          <span class="name">${titleName}, ${yearName}</span>
          <span class="population">${film.imdbID}</span>
        </li>
      `;
    }).join('');
    suggestions.innerHTML = html;
  }

  const searchInput = document.querySelector('.search');
  const suggestions = document.querySelector('.suggestions');

  searchInput.addEventListener('keyup', displayMatches);
  searchInput.addEventListener('change', displayMatches);
  searchInput.addEventListener('keyup', movieSearch);

The displayMatches function behaves inconsistently, sometimes displaying list items and other times failing to do so. Determining the root cause of this erratic behavior has proven challenging. Strangely, regardless of which method I use to call the endpoint, the content of my 'movies' array remains unchanged, adding to my confusion.

Seeking advice - Are there more effective alternatives to tackle this issue?

Currently, my HTML setup is relatively straightforward:

<form class="search-form">
 <input type="text" class="search" placeholder="Movies">
 <ul class="suggestions">
  <li>test1</li>
  <li>test2</li>
 </ul>
</form>

Thank you! (Attempting to handle this entirely in JS)

Edit:

For instance, here's the JSON response from searching 'batman' with the API:

{"Search":[{"Title":"Batman Begins","Year":"2005","imdbID":"tt0372784","Type":"movie","Poster":"https://m.media-amazon.com/images/M/MV5BZmUwNGU2ZmItMmRiNC00MjhlLTg5YWUtODMyNzkxODYzMmZlXkEyXkFqcGdeQXVyNTIzOTk5ODM@._V1_SX300.jpg"},{"Title":"Batman v Superman: Dawn of Justice","Year":"2016","imdbID":"tt2975590","Type":... (truncated)

Answer №1

Reasons for the unexpected behavior:

  1. The movieSearch function is asynchronous and may not update the data in time.
  2. Sometimes, the API returns an error.

This issue was resolved by restructuring the code below. Everything has been moved into the fetch resolver to ensure that the search only runs after receiving a response from the API.

Check out this JS Bin for the updated code: https://jsbin.com/kicesivigu/1/edit?html,js,output

  function findMatches(wordToMatch, movies) {
    return movies.filter(film => {
      console.log(film.Title, wordToMatch);
      console.log(film.Title.toLowerCase().includes(wordToMatch));
      return film.Title.toLowerCase().includes(wordToMatch) || film.Year.toLowerCase().includes(wordToMatch);
    });
  }

  function displayMatches(movies, value) {
    const matchArray = findMatches(value.toLowerCase(), movies);
    const html = matchArray.map(film => {
      const regex = new RegExp(value, 'gi');
      const titleName = film.Title.replace(regex, `<span class="hl">${value}</span>`);
      const yearName = film.Year.replace(regex, `<span class="hl">${value}</span>`);
      return `
        <li>
          <span class="name">${titleName}, ${yearName}</span>
          <span class="population">${film.imdbID}</span>
        </li>
      `;
    }).join('');
    suggestions.innerHTML = html;
  }

  const searchInput = document.querySelector('.search');
  const suggestions = document.querySelector('.suggestions');


searchInput.addEventListener('keyup', () => {
  const endpoint = 'https://www.omdbapi.com/?apikey=63f88e02&s=' + searchInput.value;

  fetch(endpoint)
    .then(blob => blob.json())
    .then(data => {
      console.log('response from API');
      console.log(data);
      if (!data.Error) displayMatches(data.Search, searchInput.value);
     });
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Are the props.children handled differently within the <Route> component compared to other React components?

Each and every react component undergoes a process in the following function, which is located in ReactElement.js within node_modules: ReactElement.createElement = function (type, config, children){ . . . } This function also encompasses <Rou ...

Combining TypeScript and JavaScript for efficient mixins

I came across an article on MDN discussing the usage and creation of mix-ins (link). Intrigued, I decided to try implementing it in TypeScript: type Constructor = new (...args: any) => any; function nameMixin(Base: Constructor) { return class extends ...

Tips for populating an HTML input with the value of a link element using JQuery

I have a form input that I want to populate with autocomplete suggestions from my database using Ajax. To style the list, I am using bootstrap 4, and I have opted to use the <a></a> tag instead of the <li></li> tag. This is because ...

Tips for resolving the issue of "Unable to assign property '_DT_CellIndex' to undefined in Jquery Datatable"

<?php if(mysqli_num_rows($result)>0) {?> <table class="table table-striped" id="example" align="center"> <tr> <thead> <th style=&quo ...

Troubleshooting: How to Fix Missing Sum Display in HTML Input Fields

I am new to the world of website programming and I am currently working on creating a basic sum equation using two input fields from the client-side. <!DOCTYPE html> <html> <head> </head> ...

Exploring the Functionality of Bootstrap 5 Collapse Component with VueJS 2

I am attempting to implement the Bootstrap 5 "collapse" component on a button in my VueJS2 project, but I am uncertain about how to integrate it. Within my single file component, the structure is as follows: <template> section: ...

"Utilizing the usePrevious hook in React: A step-by-step

After referencing the React documentation, it seems like I may not be using this code correctly. import { useEffect, useRef } from 'react'; export default function usePreviousState(state) { const ref = useRef(); useEffect(() => { ref ...

JavaScript - unable to view updated information without refreshing page

I am currently developing a Single Page Application (SPA) using Rails for the backend and JavaScript for the frontend. When I submit the initial form to create a Resource, it shows up on the page immediately upon pressing the submit button. However, when I ...

What could be causing the malfunction of Bootstrap Multiselect functionality?

I have been attempting to set up Bootstrap Multiselect but it simply refuses to work. Despite trying various solutions, I am unable to pinpoint the issue. My index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...

Developing a single page that caters to various users' needs

Greetings to all my friends, As a front end developer, I am in the process of implementing a dashboard for a project that involves different users with varying permissions. Each user should only have access to certain parts of the page, resulting in some ...

Can you explain the function of the "staticMoving" property in TrackballControls?

I was exploring the library module known as THREE.TrackballControls when I came across an interesting property within an instance of the module called staticMoving. This property appears to be connected to another property called dynamicDampingFactor. Howe ...

Node.js and MongoDB Login Form Integration with Mongoose

I am relatively new to web development and currently working on a simple web page for user login authentication. My goal is to verify user credentials (username & password) on the LoginPage from a mongoose database, and if they are correct, redirect them t ...

Is it possible to attach an onclick event to modify a data point in Chart.js?

Currently using chartjs for a small project and facing some challenges with editing data points. Is there a built-in function in this library that allows me to bind an onclick event for displaying a pop-up and removing the point? This is what I am lookin ...

Creating a flash message following a redirect in AngularJS

Just diving into Angular JS and need some clarification. How can I set a flash message after a redirect? Here's my scenario: I have a form where I save data using an HTTP request. Upon success, I navigate to another page using window.location(). Now, ...

Removing an object from the scene using three.js

Is there a way to remove an object from a three.js scene? I am trying to delete a cube when a specific key is pressed, but so far I can only clear the entire scene instead of removing just one cube. ...

A guide on retrieving the value of input elements using class names in jQuery

I need help fetching the values of input elements with the class "features". I am able to access all of them. alert($('.features').length); Can someone please confirm if my understanding is correct? $('.features') is an array of HTM ...

Effortless navigation through the document in both directions with seamless scrolling

To achieve a specific scrolling behavior on my webpage, I implemented the following function. Here is the code snippet: $(window).scroll(function(){ if ($(this).scrollTop() > 100) { $("html, body").animate({scrollTop: 700}, 500); re ...

Navigate to the specified location using AJAX

When I update a comment using AJAX, I want to automatically scroll down to the updated comment: $("#aggiorna").click(function(){ var value = $("#id").val(); var dato = $("#comment_edit").val(); var dato1 = $("#user_id").val(); var dato2 = ...

Searching for JSON array fields in a PostgreSQL database using Rails

Struggling to define a rational scope for my problem. I am trying to extract a list of Model objects with a specific "type" field within a json array column using postgresql. If anyone can guide me in the right direction, that would be helpful. I am open ...

Encountering numerous errors when importing Wallet Connect / Web3 Provider

I encountered some challenges when trying to incorporate the "@walletconnect/web3-provider" JS library into my project. After installing the library along with the Web3 module using the following command: npm install --save web3 @walletconnect/web3-provide ...