0

I am very new to Javascript and trying to print out a selected teams NFL schedule. I have created and populated a drop down menu with all the teams. I want the user to be able to select their team and see their schedule. I am able to return the whole list (every game), but I cannot figure out how to only return the games of the selected team. Here is what the data looks like that I am using.

"Schedule": [
    {
      "gameId": "1",
      "gameWeek": "1",
      "gameDate": "2018-09-06",
      "awayTeam": "ATL",
      "homeTeam": "PHI",
      "gameTimeET": "8:20 PM",
      "tvStation": "NBC",
      "winner": "PHI"
    },
    {
      "gameId": "2",
      "gameWeek": "1",
      "gameDate": "2018-09-09",
      "awayTeam": "BUF",
      "homeTeam": "BAL",
      "gameTimeET": "1:00 PM",
      "tvStation": "CBS",
      "winner": "BAL"

Here is the code that returned my all the games.

function processData(data){

  schedule = data["Schedule"];

  for(eachGame in schedule){
    var game = schedule[eachGame];
    var week = game["gameWeek"];
    var homeTeam = game["homeTeam"];
    var awayTeam = game["awayTeam"];
    var winner = game["winner"];
    var tableRow = "<tr><td>" + week + "</td><td>" + homeTeam + "</td><td>" + awayTeam + "</td><td>" + winner + "</td></tr>";
    $("#output").append(tableRow);

  }
}

I need to return when the awayTeam or homeTeam are the team that the user selected.

Thanks!

  • How do you get which team the user selected? – Max Baldwin Nov 15 '18 at 21:00
  • let team = $('#teamSelect').val(); – Zakary Krumlinde Nov 15 '18 at 21:02
  • You could use [`filter()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) to do that. `let teamSchedule = schedule.filter(g => g.homeTeam === team || g.awayTeam === team);` I'm not submitting this as an answer because I feel that this question is likely a duplicate. – Tyler Roper Nov 15 '18 at 21:13
  • Possible duplicate of [Javascript: How to filter object array based on attributes?](https://stackoverflow.com/questions/2722159/javascript-how-to-filter-object-array-based-on-attributes) – Tyler Roper Nov 15 '18 at 21:15

3 Answers3

1

To reduce an array down to only a handful of its items, I'd almost always suggest using Array.filter(), however I'm actually going to present an alternative solution first in your case.

If you were to use filter to loop through the items and find the ones you want, and then use a for loop to append them to the table, you'd be looping through some of the same elements twice.

Instead, we can apply our logic to skip the games we don't want inside the same loop, by doing something like this:

//If "team" is neither the away team, nor the home team, skip this game
if (![game.awayTeam, game.homeTeam].includes(team)) return; 

Example 1: (Comments added)

var data = { Schedule: [{ awayTeam: "Jets", homeTeam: "Bills", winner: "Bills", week: 1 }, { awayTeam: "Saints", homeTeam: "Cardinals", winner: "Cardinals", week: 1 }, { awayTeam: "Giants", homeTeam: "Bengals", winner: "Bengals", week: 2 }, { awayTeam: "Bills", homeTeam: "Jaguars", winner: "Bills", week: 2 }, { awayTeam: "Bills", homeTeam: "Patriots", winner: "Patriots", week: 3 } ] };

function setScheduleByTeam(team) {
  let schedule = data["Schedule"];    //Get the schedule
  var $outputTable = $("#output");    //Store the table as a variable
  $outputTable.find("tbody").empty(); //Empty out the current records

  schedule.forEach(function(game) {                             //For each game in the schedule
    if (![game.awayTeam, game.homeTeam].includes(team)) return; //Skip the record if our team isn't in it

    //Create + Append table row
    var tableRow = "<tr><td>" + game.week + "</td><td>" + game.homeTeam + "</td><td>" + game.awayTeam + "</td><td>" + game.winner + "</td></tr>";
    $outputTable.append(tableRow);
  });
}

//On button click
$("body").on("click", "button", function() {
  let team = $('#teamSelect').val();  //Get selected team
  setScheduleByTeam(team);            //Update the table to that team's schedule
});
td,th { padding: 5px 15px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="teamSelect">
  <option>Select Team</option>
  <option value="Bengals">Bengals</option>
  <option value="Bills">Bills</option>
  <option value="Jets">Jets</option>
</select>
<button>Go!</button>

<table id="output">
  <thead>
    <tr>
      <th>Week</th>
      <th>Home</th>
      <th>Away</th>
      <th>Winner</th>
    </tr>
  </thead>
</table>

However, some might argue for cleanliness, in which case I'd suggest going with the filter method I mentioned earlier:

Example 2 (Comments added)

var data = { Schedule: [{ awayTeam: "Jets", homeTeam: "Bills", winner: "Bills", week: 1 }, { awayTeam: "Saints", homeTeam: "Cardinals", winner: "Cardinals", week: 1 }, { awayTeam: "Giants", homeTeam: "Bengals", winner: "Bengals", week: 2 }, { awayTeam: "Bills", homeTeam: "Jaguars", winner: "Bills", week: 2 }, { awayTeam: "Bills", homeTeam: "Patriots", winner: "Patriots", week: 3 } ] };

//Filter out schedule to only games where awayTeam == team OR homeTeam == team.
//Returns the filtered team's schedule
const getGamesByTeam = (team) => data.Schedule.filter(g => g.awayTeam == team || g.homeTeam == team);

function updateScheduleTable(games) {  
  var $outputTable = $("#output");     //Store table as variable
  $outputTable.find("tbody").empty();  //Remove existing rows
  
  games.forEach(function(game) {  //For each game, append to table
    var tableRow = "<tr><td>" + game.week + "</td><td>" + game.homeTeam + "</td><td>" + game.awayTeam + "</td><td>" + game.winner + "</td></tr>";
    $outputTable.append(tableRow);
  });
  
}

$("body").on("click", "button", function() {
  let team = $('#teamSelect').val();  //Get the selected team
  let games = getGamesByTeam(team);   //Get a filtered array of one team's schedule
  updateScheduleTable(games);         //Update the table based on that set of games
});
td,th { padding: 5px 15px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="teamSelect">
  <option>Select Team</option>
  <option value="Bengals">Bengals</option>
  <option value="Bills">Bills</option>
  <option value="Jets">Jets</option>
</select>
<button>Go!</button>

<table id="output">
  <thead>
    <tr>
      <th>Week</th>
      <th>Home</th>
      <th>Away</th>
      <th>Winner</th>
    </tr>
  </thead>
</table>
Tyler Roper
  • 21,445
  • 6
  • 33
  • 56
0

You need to sort your array of data based on the user's selected team. To do that, you need to use an array method to loop over the array and return values based on logic you put in the loop. To do this, I used the reduce method (IMO the most useful array method).

function filterForSelectedTeam(data) {
  const accumulator = [];
  const team = $('#teamSelect').val();
  const schedule = data["Schedule"];
  // if team has a value this reduce method will return a sorted array
  // based on the logic in the loop.
  return team && schedule.reduce((acc, game) => {
    if (game["homeTeam"] === team || game['awayTeam'] === team) {
      acc.push(game);
    };
    return acc;
  }, accumulator);
}

const data = [] // your data here;
const gamesBySelectedTeam = filterForSelectedTeam(data)

gamesBySelectedTeam.forEach(game => {
  const tableRow = "<tr><td>" + game['gameWeek'] + "</td><td>" + game['homeTeam'] + "</td><td>" + game['awayTeam'] + "</td><td>" + game['winner'] + "</td></tr>";
  $("#output").append(tableRow);
});
Max Baldwin
  • 3,404
  • 3
  • 26
  • 40
  • 1
    While `reduce` is great if you're trying to go from many-to-one, if you're just looking to filter an array, it's much easier and cleaner to use [`.filter()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter). That said, the optimal solution would probably just be to include the "Should I display this game?" logic inside the `forEach`, that way you can use one loop instead of two :) – Tyler Roper Nov 15 '18 at 21:20
  • @TylerRoper, you should provide your own solution with the filter method to show how much "cleaner and easier" it is. Also, I wouldn't just shove all the logic into a forEach loop. I wanna show the reduction so it is easier to read for other developers. If anything I should chain the two loops. – Max Baldwin Nov 15 '18 at 21:33
  • It was merely a piece of advice. It seems you've chosen to take it as an attack instead. Not to mention, I wrote a one-line filter method in the comments above a few minutes before you submitted your answer. – Tyler Roper Nov 15 '18 at 21:39
  • @TylerRoper didn't take it as an attack. I'm just pointing out that if you have a better solution, you should provide it. That's kinda the whole point of SO. – Max Baldwin Nov 15 '18 at 21:47
  • 1
    @TylerRoper, it's just a different way of thinking that is all. I usually use `reduce` instead of `map` or `filter` because it accomplishes the same goals and you can also return different types. I appreciate your help man. – Max Baldwin Nov 15 '18 at 21:59
  • No hard feelings :) – Tyler Roper Nov 15 '18 at 22:02
0

Here is a way to do this with just a few method calls:

function processData({ Schedule: s }, team) {
  // s is now the equivolent of data['Schedule']
  // Filter the data to get all games where either
  // the away of home team is the team sent in
  // Empty the table so it includes only those games appended below
  // Append the array of games as html elements
  $("#output")empty().append(
    s.filter(g => g.awayTeam === team || g.homeTeam === team)
    .map(g => {
      `<tr>
        <td>${game.gameWeek}</td>
        <td>${game.homeTeam}</td>
        <td>${game.awayTeam}</td>
        <td>${game.winner}</td>
      </tr>`
    })
  );
}

You can append an array of html strings to the DOM and they get handled properly.

HighHopes
  • 2,014
  • 3
  • 23
  • 33