Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript JavaScript Loops, Arrays and Objects Tracking Data Using Objects The Student Record Search Challenge Solution

Doron Geyer
seal-mask
.a{fill-rule:evenodd;}techdegree
Doron Geyer
Full Stack JavaScript Techdegree Student 13,897 Points

Solution to the challenge.

let search;
let message = "";
let namesNotFound = [];
// creating a function that fills the html of the output div on the page with whatever message is provided

function print(message) {
  let output = document.getElementById("output");
  output.innerHTML = message;
}
// while loop will keep repeating the search prompt until break is triggered via cancel button or "quit" is given as an input.
while (true) {
  search = prompt(
    'please enter a student name to search for or type "quit" to exit'
  );
  search = search.toLowerCase();
  if (search === null || search === "quit") {
    break;
  }
  let notfoundCounter= 0;
  for (let index = 0; index < students.length; index++) {
    const student = students[index];
    if (search === student.name.toLowerCase()) {
      message += `<h2>student Name: ${student.name}</h2>
                 <p>student Track: ${student.track}</p>
                 <p>student Achievements: ${student.achievements}</p>
                 <p>student Points: ${student.points}</p>`;
      print(message);
    }else {
      notfoundCounter ++;
    }
  }
  if(notfoundCounter == students.length){
    namesNotFound.push(search);
    notFound = document.getElementById("notFoundOutput");
    notFound.innerHTML=`<h2> The Following were not found</h2> <p>${namesNotFound.join(', <br>')}</p>`;
  }
}

I would probably not do it this way a second time round for the alert on names not found and instead use a flag to make it a lot less complicated and easier to follow.

let notFound=true;
for(...){
   if(student.name === search){
      //do stuff
      notFound=false;
   }
}
if(notFound){
   //do more stuff
}

3 Answers

Grzegorz Zielinski
Grzegorz Zielinski
5,838 Points

I think you are nearly there.

There is still few problems with your JS:

  • It prints underneath all the things underneath each other every time you type in a name of student instead of printing "clearing" the page and printing it over again
  • 'notfoundCounter' seems to be an interesting idea, but I don't think you have to go that far, why not to make it simpler and use "else if" method to print out a message if student has not been found in array? Unless you wanted to make it a bit more complicated to practice functions and loops :)

I've made few changes to your code so it works a bit better for me:

let search;
let message = "";
// We dont need "let namesNotFound = [];" anymore

function print(message) {
  let output = document.getElementById("output");
  output.innerHTML = message;
}

while (true) {
  search = prompt(
    'please enter a student name to search for or type "quit" to exit'
  );
  search = search.toLowerCase();
  if (search === null || search === "quit") {
    break;
  }
  // We don't need "let notfoundCounter= 0;" here anymore either
  for (let index = 0; index < students.length; index++) {
    const student = students[index];
    if (search === student.name.toLowerCase()) {
      message += `<h2>student Name: ${student.name}</h2>
                 <p>student Track: ${student.track}</p>
                 <p>student Achievements: ${student.achievements}</p>
                 <p>student Points: ${student.points}</p>`;
      print(message);
    } else if (message === "") {
      print(
        `<h2>Student ${search} is not in our database, Please try again.</h2>`
      );
    }
  }
  message = ``; // This makes 'let message' go back to empty "" value every time the loops end so it doesn't print previous search results over and over again.
}

// function which is aiming "notFound Output in your HTML file is not here anymore aswell so you don't need "notFound Output" ID in your HTML file anymore.

Also here is my solution for this challenge if you wish to compare it with yours

let students = [
  { name: "Greg", track: "Web design, CSS", achievments: 763, points: 122 },
  { name: "Adam", track: "Web design", achievments: 163, points: 422 },
  { name: "Tom", track: "CSS", achievments: 653, points: 152 },
  { name: "Martin", track: "Web design, JS", achievments: 713, points: 162 },
  { name: "Ben", track: "JS, CSS", achievments: 773, points: 1127 },
  { name: "Josh", track: "JS, CSS", achievments: 773, points: 1127 },
  { name: "Tad", track: "JS, CSS", achievments: 773, points: 1127 },
  { name: "Greg", track: "JS, CSS", achievments: 1254, points: 1112 },
  { name: "Anna", track: "JS, CSS", achievments: 1254, points: 1112 },
  { name: "Tim", track: "JS, CSS", achievments: 1254, points: 1112 },
];

let message = "Type in a name of student you are looking for.";
message += ' If you wish to see all the names of our stundents type"list".';
message += ' If you wish to quit our program type "quit".';
let html;
let search;
let fulList;

// functions

function print(message) {
  var outputDiv = document.getElementById("output");
  outputDiv.innerHTML = message;
}

function list(number) {
  let position = `<li style="font-size:22px">${capitalizeFirstLetter(
    students[number].name
  )}</li>`;
  return position;
}

function capitalizeFirstLetter(string) {
  return string.charAt(0).toUpperCase() + string.slice(1);
}

function printInformation(number) {
  let print = `<h2>Student: ${students[number].name}</h2>`;
  print += `<p>Track: ${students[number].track}</p>`;
  print += `<p>Achievments: ${students[number].achievments}</p>`;
  print += `<p>Points: ${students[number].points}</p>`;
  return print;
}

// loops

while (true) {
  search = prompt(message);
  search = search.toLowerCase();
  fulList = "<h2>List</h2><ol>";
  html = " ";

  if (search === "quit" || search === 'null') {
    print("<h1>End</h2>.");
    break;
  }

  for (let i = 0; i < students.length; i += 1) {
    if (search === "list") {
      fulList += `${list(i)}`;
      html = fulList;
    } else if (search === students[i].name.toLowerCase()) {
      html += `${printInformation(i)}`;
    }
  }

  if (html === " ") {
    html = `<h2>Student ${capitalizeFirstLetter(
      search
    )} is not in our base, sorry. Try again.</h2>`;
  }

  print(html);
}

It's quite similar, I've extended it by "list" option which lets you print all the students names on a page.

Hope it helps!

Doron Geyer
seal-mask
.a{fill-rule:evenodd;}techdegree
Doron Geyer
Full Stack JavaScript Techdegree Student 13,897 Points

thanks for the feedback, the else if method in this case would cause multiple repeats as it loops through when you use

else if(not found){
   alert( not found) 
}

it will give you that response 4 times because for each loop through the array 4/5 will not be found. That is why I mentioned if I had to redo this I would use a flag to set it up.

with the list being printed under each other I did this so that if you were to run multiple searches you would get all relevant results. So if you type Dave and then Jody into the search bar you would not end up only getting results for jody , but instead would get results for both Dave and Jody ( 1 and 2 ). The same goes for the not found result. If you search for 10 names and 8 were not found , would you want to know only the most recent search not found or get a list of results that didnt match? I think it makes more practical sense to get feedback on all of them incase there was a problem with either your input or with the creation of a student record.

I like the addition of the list function, and the capitalisation which I was a bit lazy to do. Nice all round solutions.

help me solve this problem of mine. i can get student record and my code is exactly like the teachers . am not using document.write as you can see in my code https://w.trhou.se/cvykpthgo2

Doron Geyer
seal-mask
.a{fill-rule:evenodd;}techdegree
Doron Geyer
Full Stack JavaScript Techdegree Student 13,897 Points

Hi musab abdi you need to open a new post or people wont see your question as you have just posted a comment on I believe Grzegorz has answered it below.

In future use the help feature and people will easily be able to see your questions and assist you a lot faster best of luck !

Grzegorz Zielinski
Grzegorz Zielinski
5,838 Points

There is a small mistake in your code which doesn't let JS go through whole script.

var student;
var search;
var outputMsge='';
function printToPage(message){
var div = document.querySelector('#output');
  div.innerHTML =message;
}
function studentReport(student){
    var report = `<h2>student: ${student.name}</h2>`;
      report+=`<p>track: ${student.track}</p>`;
      report+=`<p>achievements: ${student.achievements}</p>`;
      report+=`<p>points: ${student.points}</p>`;
      return report;
}
while(true){
search = prompt(`type your name to get report or type quit to exit the page`);
  if(search === null || search.toLowerCase() === 'quit'){
    break;
  } 
} // this curly brace here ends your "while infinite" loop, which makes your JS run over and over again through ONLY this part of script, and not going further to next part underneath.  

for(i=0; i< students.length; i+=1){
  student=students[i];
    if(search === student.name){
      outputMsge = studentReport(student);
      printToPage(outputMsge);
    }
  }

So to fix it you should move that curly brace after second loop so your "while infinite" loop can go through whole script and compare "search" with "student.name" and print out the message if it's been found.

Here is the correct way:

var student;
var search;
var outputMsge = "";
function printToPage(message) {
  var div = document.querySelector("#output");
  div.innerHTML = message;
}

function studentReport(student) {
  var report = `<h2>student: ${student.name}</h2>`;
  report += `<p>track: ${student.track}</p>`;
  report += `<p>achievements: ${student.achievements}</p>`;
  report += `<p>points: ${student.points}</p>`;
  return report;
}

while (true) {
  search = prompt(`type your name to get report or type quit to exit the page`);

  if (search === null || search.toLowerCase() === "quit") {
    break;
  }
 // I removed curly brace here
  for (i = 0; i < students.length; i += 1) {
    search = search.toLowerCase();
    student = students[i];
    if (search === student.name.toLowerCase) {
      outputMsge = studentReport(student);
      printToPage(outputMsge);
    }
  }
} // and I've added it here

I've also added ".toLowerCase()" method so loop now ignores a size of a letters you type in when asked for student name.

Hope it helps!