Discover a JavaScript table using a for loop

Currently, I'm in the process of setting up a search bar within a table that has been populated by looping data retrieved from an API. My goal is to allow users to search for specific entries either by name or email. Unfortunately, I seem to be encountering an issue as the console displays an uncaught ReferenceError: sBar is not defined at window.onload. Please bear in mind that I am new to JavaScript and struggling with this problem. I apologize if this is trivial, but despite my best efforts, I can't seem to identify the mistake.

Below is my HTML:

<body>
  <div>
    <label for="finder">Find User:</label>
    <input type="search" id="searchInput" name="sInput" placeholder="Search 
    user">
    <button id="sButton">Search</button>
  </div>
  <table class="table table-responsive">
    <thead class="thead-dark">
      <tr>
        <th scope="col">Id</th>
        <th scope="col">Name</th>
        <th scope="col">Username</th>
        <th scope="col">Email</th>
        <th scope="col">Address</th>
        <th scope="col">Phone</th>
        <th scope="col">Website</th>
        <th scope="col">Company</th>
      </tr>
    </thead>
    <tbody name="tTable">
    </tbody>
  </table>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js">
</script>
<script src="script.js">
</script>

My JavaScript code:

window.onload = function(){    

    let uList = document.querySelector('[name=tTable]');  

    fetchCall('https://jsonplaceholder.typicode.com/users', getUsers);
    sButton.addEventListener('click', fetchCall('https://jsonplaceholder.typicode.com/users', sBar), false);


  function sBar(getObject) {
    let sUser = getObject;
    let inputBar = document.getElementById("searchInput");
    let text = inputBar.textContent;
    let textView = text.toUpperCase();
    for (let i = 0; i < getObject.length; i++) {
         let uObject = sUser[i];
      if (textView == uObject.name || textView == uObject.email) {
        let new_tTable = document.createElement('tbody');
        uList.parentNode.replaceChild(new_tTable, uList)

        let row = uList.insertRow();   
        let idInput = document.createElement('td');
        let nameInput = document.createElement('td');     
        let usernameInput = document.createElement('td');    
        let emailInput = document.createElement('td');      
        let cityInput = document.createElement('td');   
        let phoneInput = document.createElement('td');      
        let websiteInput = document.createElement('td');      
        let companyInput = document.createElement('td');      

        idInput.textContent = uObject.id;
        nameInput.textContent = uObject.name;
        usernameInput.textContent = uObject.username;
        emailInput.textContent = uObject.email;
        cityInput.textContent = uObject.address.city;
        phoneInput.textContent = uObject.phone;
        websiteInput.textContent = uObject.website;
        companyInput.textContent = uObject.company.name;
        row.appendChild(idInput);
        row.appendChild(nameInput);
        row.appendChild(usernameInput);
        row.appendChild(emailInput);
        row.appendChild(cityInput);
        row.appendChild(phoneInput);
        row.appendChild(websiteInput);
        row.appendChild(companyInput);  
     } else {
       alert("User not found");         
     }
   }
} 


  function fetchCall(url, fn){
    fetch(url)
        .then(function(response){
            return response.json();
        })
        .then(function(endPoint){
            fn(endPoint);
        })
        .catch(function(error){
            console.error(error);
        })
    }

  function getUsers(getObject) {
    let user = getObject;      
      for (let i = 0; i < getObject.length; i++) {
        let userObject = user[i];
        let row = uList.insertRow();   
        let idInput = document.createElement('td');
        let nameInput = document.createElement('td');     
        let usernameInput = document.createElement('td');    
        let emailInput = document.createElement('td');      
        let cityInput = document.createElement('td');      
        let phoneInput = document.createElement('td');      
        let websiteInput = document.createElement('td');      
        let companyInput = document.createElement('td');      

        idInput.textContent = userObject.id;
        nameInput.textContent = userObject.name;
        usernameInput.textContent = userObject.username;
        emailInput.textContent = userObject.email;
        cityInput.textContent = userObject.address.city;
        phoneInput.textContent = userObject.phone;
        websiteInput.textContent = userObject.website;
        companyInput.textContent = userObject.company.name;
        row.appendChild(idInput);
        row.appendChild(nameInput);
         row.appendChild(usernameInput);
         row.appendChild(emailInput);
         row.appendChild(cityInput);
         row.appendChild(phoneInput);
         row.appendChild(websiteInput);
         row.appendChild(companyInput);        
        }
      } 
    }

Answer №1

When you schedule an event, ensure to bind the function for proper execution.

sButton.addEventListener('click', fetchCall.bind(this, 'https://jsonplaceholder.typicode.com/users', sBar), false);

It is advisable to create a function in the global context as well.

uList = document.querySelector('[name =tTable]');

window.onload = function () {
    fetchCall('https://jsonplaceholder.typicode.com/users', getUsers);
    sButton.addEventListener('click', fetchCall.bind(this, 'https://jsonplaceholder.typicode.com/users', sBar), false);
}

function sBar(getObject) {
    let sUser = getObject;
    let inputBar = document.getElementById("searchInput");
    let text = inputBar.textContent;
    let textView = text.toUpperCase();
    for (let i = 0; i < getObject.length; i++) {
        let uObject = sUser[i];
        if (textView == uObject.name || textView ==
            uObject.email) {
            let new_tTable = document.createElement('tbody');
            uList.parentNode.replaceChild(new_tTable, uList)


            let row = uList.insertRow();
            let idInput = document.createElement('td');
            let nameInput = document.createElement('td');
            let usernameInput = document.createElement('td');
            let emailInput = document.createElement('td');
            let cityInput = document.createElement('td');
            let phoneInput = document.createElement('td');
            let websiteInput = document.createElement('td');
            let companyInput = document.createElement('td');

            idInput.textContent = uObject.id;
            nameInput.textContent = uObject.name;
            usernameInput.textContent = uObject.username;
            emailInput.textContent = uObject.email;
            cityInput.textContent = uObject.address.city;
            phoneInput.textContent = uObject.phone;
            websiteInput.textContent = uObject.website;
            companyInput.textContent = uObject.company.name;
            row.appendChild(idInput);
            row.appendChild(nameInput);
            row.appendChild(usernameInput);
            row.appendChild(emailInput);
            row.appendChild(cityInput);
            row.appendChild(phoneInput);
            row.appendChild(websiteInput);
            row.appendChild(companyInput);
        } else {
            alert("User not found");
        }
    }
}


function fetchCall(url, fn) {
    fetch(url)
        .then(function (response) {
            return response.json();
        })
        .then(function (endPoint) {
            fn(endPoint);
        })
        .catch(function (error) {
            console.error(error);
        })
}

function getUsers(getObject) {
    let user = getObject;
    for (let i = 0; i < getObject.length; i++) {
        let userObject = user[i];
        let row = uList.insertRow();
        let idInput = document.createElement('td');
        let nameInput = document.createElement('td');
        let usernameInput = document.createElement('td');
        let emailInput = document.createElement('td');
        let cityInput = document.createElement('td');
        let phoneInput = document.createElement('td');
        let websiteInput = document.createElement('td');
        let companyInput = document.createElement('td');

        idInput.textContent = userObject.id;
        nameInput.textContent = userObject.name;
        usernameInput.textContent = userObject.username;
        emailInput.textContent = userObject.email;
        cityInput.textContent = userObject.address.city;
        phoneInput.textContent = userObject.phone;
        websiteInput.textContent = userObject.website;
        companyInput.textContent = userObject.company.name;
        row.appendChild(idInput);
        row.appendChild(nameInput);
        row.appendChild(usernameInput);
        row.appendChild(emailInput);
        row.appendChild(cityInput);
        row.appendChild(phoneInput);
        row.appendChild(websiteInput);
        row.appendChild(companyInput);
    }
}

Answer №2

Separating the window.onload and other functions might be a good idea.

window.onload = function(){    

    let userList = document.querySelector('[name =tTable]');  

    fetchCall('https://jsonplaceholder.typicode.com/users', getUsers);
    searchButton.addEventListener('click', 
    fetchCall('https://jsonplaceholder.typicode.com/users', searchBar), false);
};

  function searchBar(getObject) {
    let searchUser = getObject;
    let inputBar = document.getElementById("searchInput");
    let text = inputBar.textContent;
    let textView = text.toUpperCase();
    for (let i = 0; i < getObject.length; i++) {
         let userObject = searchUser[i];
        if (textView == userObject.name || textView == 
       userObject.email) {
        let newTable = document.createElement('tbody');
        userList.parentNode.replaceChild(newTable, userList)

        let row = userList.insertRow();   
        let idInput = document.createElement('td');
        let nameInput = document.createElement('td');     
        let usernameInput = document.createElement('td');    
        let emailInput = document.createElement('td');      
        let cityInput = document.createElement('td');      
        let phoneInput = document.createElement('td');      
        let websiteInput = document.createElement('td');      
        let companyInput = document.createElement('td');      

        idInput.textContent = userObject.id;
        nameInput.textContent = userObject.name;
        usernameInput.textContent = userObject.username;
        emailInput.textContent = userObject.email;
        cityInput.textContent = userObject.address.city;
        phoneInput.textContent = userObject.phone;
        websiteInput.textContent = userObject.website;
        companyInput.textContent = userObject.company.name;
        row.appendChild(idInput);
        row.appendChild(nameInput);
         row.appendChild(usernameInput);
         row.appendChild(emailInput);
         row.appendChild(cityInput);
          row.appendChild(phoneInput);
         row.appendChild(websiteInput);
         row.appendChild(companyInput);  
          } else{
           alert("User not found");
               }
       }
   } 


  function fetchCall(url, fn){
    fetch(url)
        .then(function(response){
            return response.json();
        })
        .then(function(endPoint){
            fn(endPoint);
        })
        .catch(function(error){
            console.error(error);
        })
    }

  function getUsers(getObject) {
    let user = getObject;      
      for (let i = 0; i < getObject.length; i++) {
        let uObject = user[i];
        let row = userList.insertRow();   
        let idInput = document.createElement('td');
        let nameInput = document.createElement('td');     
        let usernameInput = document.createElement('td');    
        let emailInput = document.createElement('td');      
        let cityInput = document.createElement('td');      
        let phoneInput = document.createElement('td');      
        let websiteInput = document.createElement('td');      
        let companyInput = document.createElement('td');      

        idInput.textContent = uObject.id;
        nameInput.textContent = uObject.name;
        usernameInput.textContent = uObject.username;
        emailInput.textContent = uObject.email;
        cityInput.textContent = uObject.address.city;
        phoneInput.textContent = uObject.phone;
        websiteInput.textContent = uObject.website;
        companyInput.textContent = uObject.company.name;
        row.appendChild(idInput);
        row.appendChild(nameInput);
         row.appendChild(usernameInput);
         row.appendChild(emailInput);
         row.appendChild(cityInput);
         row.appendChild(phoneInput);
         row.appendChild(websiteInput);
         row.appendChild(companyInput);        
        }
      } 

Answer №3

You've connected a callback function sBar() to an event called onchange for the search input, but there's no actual definition of the sBar() function (which doesn't require any arguments/parameters). Instead, you've defined a function with the same name, "sBar", that actually requires a parameter named getObject.

To fix this issue, remove the parameter "getObject" and adjust the initial code lines to retrieve the text entered in the search input field. Here's an example code snippet to get the value entered in your search input:

var value = document.getElementById("searchInput").value;

Additionally, keep in mind that using onchange might not be the most appropriate event emitter as it only triggers when you move focus away from the input field, not during actual typing.

If you want to monitor changes while they type, consider using "onkeydown". For capturing paste events via mouse, use "onpaste" (IE, FF3) or "oninput" (FF, Opera, Chrome, Safari1).

For more information, refer to this link

Answer №4

Async/Await & Fetch()

The main functionality is built using Async/Await and Fetch(). For detailed syntax, please visit the provided link.

Addressing all issues with the original post code seems challenging to me. It's advisable to break down the process into steps:

  1. Retrieve JSON data from the URL. Are you confident that fetchAll() functions as expected?

  2. Once you successfully fetch the JSON using fetchCall(), transfer it to getUser().

  3. If fetchCall() returns a value (which seems likely...) treat the entire function as a value.

  4. Event listeners and handlers have specific signatures that need to be followed, whether utilizing a named or anonymous callback:

Named Callback (No Parameters*)

DOMObj.addEventListener('event', namedFunction);
function namedFunction(e) {...

Named Callback (With Parameters)

DOMObj.addEventListener('event', function(e) {
  namedFunction(num, str);
});
function namedFunction(num, str) {...

Anonymous Callback

DOMObj.addEventListener('event', function(e) {...

In the following demonstration, an async function getUser(url, id) is utilized to simplify Promises, make use of fetch(), and extract JSON data one user ID at a time. The returned result by getUser() includes the JSON along with the function getData(<strong>json</strong>).

The search input has been modified to type='number' since users are referenced by their user.id property. Additionally, it is wrapped within a <form> tag to trigger the callback function findUser(url, id) upon form submission - essentially acting as a wrapper for getUser().


Demo

<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet">
<style>
fieldset.fieldset {width:max-content;padding: 10px 0 0}
input.input, label.label {display:inline-block;font:inherit;width:9ch;height:30px;line-height:30px;vertical-align:middle;text-align:center;}
input.input {width:6ch;padding-right:0;margin-right:8px}
input.button {font:inherit;height: 30px;line-height:20px;}
</style>
</head>
<body>
  <main class='container'>
    <section class='row'>
      <form id='main' class='form inline-form'>
        <fieldset class='fieldset form-group'>
          <label class='label control-label float-left' for="find">User ID:</label>
          <input id="find" class='input form-control float-left' type="number" min='1' max='10'>
          <input class="button btn btn-dark btn-sm float-left" type='submit' value='Find'>
       </fieldset>
    </form>
  </section>
  <section class='row'>
  <table class="table table-responsive">
    <thead class="thead-dark">
      <tr>
        <th scope="col">ID</th>
        <th scope="col">Name</th>
        <th scope="col">Username</th>
        <th scope="col">Email</th>
        <th scope="col">Phone</th>
        <th scope="col">Company</th>
        <th scope="col">City</th>
        <th scope="col">Website</th>
      </tr>
    </thead>
  </table>
 </section>
</main>
<script>

const main = document.forms[0];

const getData = (user) => {
  const uList = document.querySelector('.table');
  let row = uList.insertRow();  
  let cell = idx => row.insertCell(idx);
  
  for (let i = 0; i < 8; i++) {
    let C = cell(i);
    switch(i) {
      case 0:
      user.id = user.id > 9 ? "" + user.id: "0" + user.id;
      C.textContent = user.id;
      break;
      case 1:
      C.textContent = user.name;
      break;
      case 2:
      C.textContent = user.username;
      break;
      case 3:
      C.textContent = user.email;
      break;
      case 4:
      C.textContent = user.phone;
      break;
      case 5:
      C.textContent = user.company.name;
      break;
      case 6:
      C.textContent = user.address.city;
      break;
      case 7:
      C.textContent = user.website;
      break;
      default:
      break;
    }
  } 
};

const getUser = async (url, id) => { 
  const response = await fetch(`${url}${id}`);
  const json = await response.json();
  return getData(json);
};

/*/ For debugging -- an IIFE variables are private. Parameters are required.
(async (u, i) => {
  const json = await getUser(u, i);
  console.log(json);
})(url, id);
/*/

const findUser = (e) => {
  e.preventDefault();
  const url = 'https://jsonplaceholder.typicode.com/users/';
  let id = Number(e.currentTarget.find.value);
  getUser(url, id);
};

main.addEventListener('submit', findUser);

</script>
</body>
</html>

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

Converting plain text to a JSON object using JavaScript: A step-by-step guide

Having trouble converting plain text into JSON value in Javascript. Need some assistance. Actual string obtained from a command line executed through Javascript: Net State: OFFLINE Net Err: Net Time: 0 Current Sample: 0 Sample #0 Sample Role: O ...

Utilizing Node.js to insert a new image path into MongoDB

I have successfully stored image paths in MongoDB in array format. Now, I need to figure out how to add another image path to the existing array using the document ID. How can I achieve this in MongoDB? Currently, I am uploading images using an HTML file. ...

What is the process for uploading a file using the client's file path?

I'm fascinated by the way Sonic Living is able to identify and upload your iTunes library XML file with such ease. Unlike other upload libraries I've explored, it prompts user approval before automatically uploading the XML file based on client O ...

Programmatically control the opening and closing of a React Material UI Snackbar component

Currently, I am facing some challenges while working on programming a Single Page Application (SPA) using React and Material-UI. In my project, I have created a modal login box that gets triggered by a button on the navigation bar. Upon clicking submit, I ...

Locate the element within the specified parameters using [protractor]

Here's my query: element.all(by.repeater('user in users')).then(function(rows) { // looking to locate an element in rows using CSS selector, for example } UPDATE : I want to clarify that I am trying to find an element using rows[rows.len ...

Change the <base> element programmatically during server-side rendering

Searching for a way to obtain the base URL for an HTML page, so that relative URL requests from the browser utilize that base. If you are looking for answers, check out this link: Defining root of HTML in a folder within the site root folder When serving ...

Sequential asynchronous requests with a time delay

let updateData = function() { $.ajax({ . . . }) .done(function() { console.log('Update complete'); setInterval(updateData, 10000); }); } I am trying to update some data every 10 seconds. Ho ...

Prepare an email message for sending

Currently, I'm working on an app using officejs. My goal is to extract content from an Excel worksheet and insert it into an Outlook email. However, I don't want the email to be automatically sent by the system. Instead, I would like the new emai ...

Customizing Pie Legends in Echart Configuration

I am trying to find a way to present pie chart legends along with their values in a unique format. I have attached an image for reference. Despite my efforts, I haven't been able to figure out how to achieve this specific display. If you take a look a ...

What are the proper methods for accurately testing vuex state and mutations?

Can someone guide me on how to properly test mutations and state? I have a modal window component that is rendered when the showModal property in the state is true. There is an event triggering a mutation that changes this property. How can I verify that a ...

Check to see if two sets of coordinates fall within the specified radius

I'm currently working on analyzing the collision data for major intersections in my city by aggregating it with the location information. My main goal is to determine the number of accidents that occurred within a 20-meter radius of each intersection. ...

Add the onclick() functionality to a personalized Angular 4 directive

I'm facing an issue with accessing the style of a button in my directive. I want to add a margin-left property to the button using an onclick() function in the directive. However, it doesn't seem to be working. Strangely, setting the CSS from the ...

completed() versus finished()

As I was going through the documentation for passport, I came across an interesting observation regarding the use of serialize() and deserialize(). It seems that done() is called without being explicitly returned in one scenario. However, while setting up ...

``There is an issue with the onsubmit property that prevents the opening of

I have encountered an issue with my forms that has me stumped. Despite searching online for help, I can't seem to figure out why my implementation is not working as intended. The concept is straightforward. I've embedded a form within a JSP page ...

Fixing a scrolling element within a div located below the screen is my goal, ensuring it remains fixed in place as the user scrolls

I'm facing a challenge that I need help with: My HTML/CSS layout currently looks like this: Screenshot of how my CSS/HTML appears on the screen upon page load: As I scroll down, I encounter a green element: While scrolling down -> Upon further s ...

Adding an image to a React component in your project

I am currently working on an app that utilizes React and Typescript. To retrieve data, I am integrating a free API. My goal is to incorporate a default image for objects that lack images. Here is the project structure: https://i.stack.imgur.com/xfIYD.pn ...

DataTables ajax feature is not functioning

Looking to implement AJAX in this table using the following code snippet: $('#example').DataTable({ 'serverSide': true, "bPaginate": false, "info": false, "iDisplayLength":20, "bLengthChange":false, 'ajax&a ...

Determine distinct items in an array that match a predefined criteria

I have a list of objects with two keys, img1 and img2. I need to identify unique objects based on the values of img1, while also retaining the corresponding value of img2. This is the current code I am using: const imgs_arr = [ ...new Set( inpu ...

I am attempting to separate this "for" loop in order to generate five distinct DIV elements

Hello there! I am a beginner and I am attempting to create 5 different players by using some code that I found. Here is the code I have been working with: https://codepen.io/katzkode/pen/ZbxYYG My goal is to divide the loop below into 5 separate divs for ...

When a large object changes value in Firebase, does it transfer only the delta change in internet bandwidth?

Hello, I am working with a node that contains an array of 1000 nodes, totaling around 60KB in size. rootRef.on('value', function (snapshot){ //callback every changes props , full list obj }); I would like to know: - When a node in ...