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

Creating a link using curly braces {{ }} in VUE js

I need assistance in creating links to different pages using data in curly brackets {{ }}, I am having trouble figuring out the correct way to implement them. <div id="app"> <div v-for="data in categorie"> &l ...

The addition of days is producing an incorrect result

When extracting the date from FullCalendar and attempting to edit it, I noticed that moment.js seems to overwrite all previously saved dates. Here is an example of what's happening: var date_start = $calendar.fullCalendar('getView').start.t ...

Retrieving data in Next.js

Exploring various techniques to retrieve information from APIs in next.js. Options include getServerSideProps, getStaticPaths, getStaticProps, Incremental Static Regeneration, and client-side rendering. If I need to send requests to the backend when a s ...

Connecting prop variables to component variables establishes a direct relationship between them

By assigning the props variable to a component variable, any changes made to the component variable will also reflect in the props... Parent Component: const prova = [ { 1: 'a' }, { 2: 'b' }, { ...

Confirm the email address using the autocomplete feature in the field

I'm currently utilizing Material UI to design an autocomplete field with multiple inputs that gives users the option to either choose from existing email addresses or input their own. An example of what I'm trying to achieve can be seen here: ht ...

The Facebook Comments feature on my React/Node.js app is only visible after the page is refreshed

I am struggling with getting the Facebook Comment widget to display in real-time on my React application. Currently, it only shows up when the page is refreshed, which is not ideal for user engagement. Is there a way to make it work through server-side r ...

Can you explain the purpose of the equals sign in ngRepeat?

Can you explain the significance of the equals sign in the ng-repeat attribute value? <li ng-repeat="person in people = (people | orderBy: firstname)"> rather than using: <li ng-repeat="person in people | orderBy: firstname"> I coul ...

There seems to be an issue with the Alexa skill's ability to provide a response after another

I am currently developing an Alexa skill that involves a multi-step dialog where the user needs to respond to several questions one after the other. To begin, I am trying to kick things off by implementing a single slot prompt. I am checking if the slot is ...

What is the preferred method for verifying AJAX success when the server's response is either true or false?

My server response can be either true or false. I've been attempting to determine how to check for success based on the returned value being true or false using the script below: $('form[data-async]').on('submit', function(event) ...

How to clear a 24-hour-old template from the Angular 1 cache?

I have implemented the following rule to clear template cache in my AngularJS application: myApp.run(function ($rootScope, $templateCache) { $rootScope.$on('$viewContentLoaded', function() { $templateCache.removeAll(); }); }); Howe ...

A guide on integrating a submission button that combines values from multiple dropdown forms and redirects to a specific URL

Is there a way to make the submit button on this form act based on the combined values of two different dropdown menus? For instance, if "west" is selected from the first dropdown and "winter" is selected from the second dropdown, I want it to navigate to ...

Issue with executing Jquery in PUG file: The $ sign is not being recognized despite jQuery being imported

I am encountering an issue where my jQuery code placed inside a pug template is not executing as expected. Despite including the jQuery file, when trying to run a jQuery function, I receive the error below: 40| P 41| ...

React and D3 Force Layout: uncharted territories for new links' positions

After carefully following the general update pattern for new React Props, I've noticed that D3 efficiently handles data calculation and rendering when receiving new props. This prevents React from having to render every tick. D3 functions seamlessly ...

Angular Material (8) error code S2591: The variable 'require' is not defined in the current scope

Currently, I am attempting to record the date and time in the JavaScript console. Despite the code successfully logging the dates, an error message persists: Note: The code is functioning properly, with the dates being displayed in the console. It is only ...

The information is undefined, yet it is being recorded in the console

After retrieving data from the backend, it seems to be undefined when I try to use it. However, I can see the data logged in the console when using console.log. //I attempted to fetch data using axios but encountered a 404 error and received und ...

Using V-bind to assign multiple classes has never been easier

Is there a way to assign one of two classes to an element based on three possible input variables in my Vue.js code? <input type='text' class='inputwordtext' v-bind:class="{(wordupload.firstchoice.selected == 'Zinnenlijst' ...

The call stack in mongodb has surpassed its maximum size limit

I am currently executing a method. Method execution var message = "Hello" function1("78945612387", message, null, "Portalsms") Node JS Code function function1(mobileno,body,logExtraInfo,messageType){ request(uri, function (error, resp ...

What is the best way to display a div based on a keyword match?

If the keyword search results in a match, I can display the corresponding input text and its related category div. Now, I am attempting to also search through category names. If the searched keyword matches a category name, that specific div should be visi ...

What is the best way to prevent labels from floating to the top when in focus?

How can I prevent the label from floating on top when focusing on a date picker using Material UI? I have tried several methods but nothing seems to work. I attempted using InputLabelProps={{ shrink: false }} but it did not resolve the issue. Here is a li ...

Rows in the table are not extending to their full length

I'm having an issue with my Bootstrap table design. I have 8 header cells and 5 body cells, but the rows are only stretching across 4 columns. I've hit a blank trying to figure out why. <script src="https://cdnjs.cloudflare.com/ajax/libs/jq ...