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!
3 Answers 3
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>
Comments
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);
});
6 Comments
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(). 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 :)reduce instead of map or filter because it accomplishes the same goals and you can also return different types. I appreciate your help man.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.
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.