Who can help me create a favorite list of teams for example that I can then display on another page and do this with local storage? The list comes from a SQL database.
At the end of the list (table) there is a heart icon, which you can click on. When you click on the heart icon it changes into another icon. But when I refresh the page I want to see the selected items again. Also, when I open another page, I get a list of my selected items.
teams.cshtml
:
@page
@model organizer.Pages.TeamsModel
@using Microsoft.AspNetCore.Http
@addTagHelper*, Microsoft.AspNetCore.Mvc.TagHelpers
@{
Layout = "_Layout2";
}
<div class="eigentabel">
<h3 class="text-end"> @Model.variabelTNaam</h3>
@foreach (var itemD in Model.listDivisieD)
{
//hier zetten we de titel op de pagina
<span><h2>@itemD.naam </h2></span>
<table id="" class="display">
@{
Model.nummer = 0;
}
<thead>
<tr>
<th style="width: 2%">#</th>
<th style ="text-align: center; width: 2%"></th>
<th style="text-align: left; width: 10%">Team name</th>
<th style="width: 5%">Country</th>
<th style="width: 5%">Payed on</th>
<th style="width: 5%">Like</th>
</tr>
</thead>
<tbody>
@foreach (var itemT in Model.listTeamT)
{
if (itemT.divisie == @itemD.naam)
{
<tr>
@{
Model.nummer = Model.nummer + 1;
}
<td>@Model.nummer</td>
<td><img src="https://@itemT.vlag" width="20" height="13"></td>
<td><a asp-page-handler="Team" asp-route-varTeamId="@itemT.id">@itemT.naam</a></td>
<td>@itemT.land</td>
<td>@itemT.betaling</td>
<td><i onclick="myFunction(this)" id="hartje" class="fa fa-heart-o"></i></td>
</tr>
}
}
</tbody>
</table>
}
</div>
teams.cshtml.cs
:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Data.SqlClient;
namespace organizer.Pages
{
public class TeamsModel : PageModel
{
public String? variabelTNaam;
public List<TeamInfoT> listTeamT = new();
public List<DivisieInfoD> listDivisieD = new();
public string? sessionvarTorId;
public int nummer;
private readonly IConfiguration _configuration;
//Dit moeten we hier zetten en de variabele instellen
public void OnGetTeamAsync(Guid? varTeamId)
{
HttpContext.Session.SetString("SessionTeamId", varTeamId.ToString());
Response.Redirect("/Team_detail");
}
public TeamsModel(IConfiguration configuration)
{
_configuration = configuration;
}
public void OnGet()
{
// Set value in Session object.
if (HttpContext.Session.GetString("SessionTorId") != null)
sessionvarTorId = HttpContext.Session.GetString("SessionTorId");
try
{
string connString = _configuration.GetConnectionString("DefaultConnection");
using SqlConnection connection = new(connString);
connection.Open();
String sqlD = "SELECT .....";
String sqlT = "SELECT ...";
String sql1 = "SELECT ...";
using SqlCommand command1 = new(sql1, connection);
variabelTNaam = (string)command1.ExecuteScalar();
using (SqlCommand commandD = new(sqlD, connection))
{
using SqlDataReader readerD = commandD.ExecuteReader();
while (readerD.Read())
{
DivisieInfoD divisieInfoD = new()
{
id = readerD.GetGuid(0),
naam = readerD.GetString(2),
maxTeams = readerD.GetInt32(14),
};
listDivisieD.Add(divisieInfoD);
}
}
using SqlCommand commandT = new(sqlT, connection);
{
using SqlDataReader readerT = commandT.ExecuteReader();
while (readerT.Read())
{
TeamInfoT teamInfoT = new()
{
id = readerT.GetGuid(0),
naam = readerT.GetString(1),
land = readerT.GetString(2),
vlag = readerT.GetString(3).ToString().ToLower().Replace(" ", "_"),
betaling = readerT.IsDBNull(4) ? "-" : readerT.GetDateTime(4).ToString("dd-MMM-yyyy"),
divisie = readerT.GetString(5),
};
listTeamT.Add(teamInfoT);
}
}
}
catch (Exception ex)
{
Console.WriteLine("NOT Connected");
Console.WriteLine("Exception: connectie NIET ok " + ex.Message);
}
}
}
public class DivisieInfoD
{
public String? naam;
public Guid? id;
public int maxTeams;
}
public class TeamInfoT
{
public Guid id;
public String? naam;
public String? land;
public String? vlag;
public String? betaling;
public String? divisie;
}
}
_layout2.cshtml
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - TEST</title>
<!-- DataTables -->
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.2.0/css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css" />
<link rel="stylesheet" href="~/js/datatables.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js" />
<link href="~/css/site.css" rel="stylesheet" />
<!-- Font Awesome CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<header>
<div class="fixed-top">
<nav class="navbar navbar-expand-sm navbar-toggleable-sm bg-primary navbar-dark border-bottom box-shadow mb-3 ">
<div class="container-fluid">
<div class="navbar-left">
<a class="navbar-brand" target="_blank">
</a>
</div>
<div class="navbar-right">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-end">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-light " style="margin-left:1em" asp-area="" asp-page="/Index"><span class="fa fa-home"></span> Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-light " style="margin-left:1em" asp-area="" asp-page="/Tornooi_Algemeen"><span class="fa fa-dashboard"></span> Dashboard</a>
</li>
</ul>
</div>
</div>
</div>
</nav>
</div>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© - <a asp-area="" asp-page="/Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
<script type="text/javascript">
//function changing heart
function myFunction(x) {
x.classList.toggle("fa-thumbs-up");
window.localStorage.setItem("FavoriteTeam", "test");
}
// Initialize the DataTable
$(document).ready(function () {
$('table.display').DataTable({
// Set the number of rows to be
// displayed per page on the DataTable
pageLength: 25,
lengthMenu: [25, 50]
});
});
// Initialize the DataTable
$(document).ready(function () {
$('table.display2').DataTable({
"dom": "<'row'<'col-lg-10 col-md-10 col-xs-12'f><'col-lg-2 col-md-2 col-xs-12'l>>" +
"<'row'<'col-sm-12'tr>>" +
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
// Set the number of rows to be
// displayed per page on the DataTable
pageLength: 25,
lengthMenu: [25, 50, 100]
});
});
</script>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-4CPZWF653F"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', 'G-4CPZWF653F');
</script>
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
You could try below code:
Data/ApplicationDbContext.cs:
using Microsoft.EntityFrameworkCore;
using System.Text.Json.Serialization;
namespace FavoriteTeams.Data
{
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Team> Teams { get; set; }
public DbSet<Division> Divisions { get; set; }
}
public class Team
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Country { get; set; }
public string Flag { get; set; }
public DateTime? Payment { get; set; }
public Guid DivisionId { get; set; }
[JsonIgnore]
public Division Division { get; set; }
}
public class Division
{
public Guid Id { get; set; }
public string Name { get; set; }
public int MaxTeams { get; set; }
[JsonIgnore]
public ICollection<Team> Teams { get; set; }
}
}
Data/DbInitializer.cs:
using Microsoft.EntityFrameworkCore;
namespace FavoriteTeams.Data
{
public class DbInitializer
{
public static void Initialize(IServiceProvider serviceProvider)
{
using (var context = new ApplicationDbContext(
serviceProvider.GetRequiredService<DbContextOptions<ApplicationDbContext>>()))
{
if (context.Divisions.Any() || context.Teams.Any())
{
return; // DB has been seeded
}
var divisions = new Division[]
{
new Division { Id = Guid.NewGuid(), Name = "Division 1", MaxTeams = 10 },
new Division { Id = Guid.NewGuid(), Name = "Division 2", MaxTeams = 10 }
};
foreach (var d in divisions)
{
context.Divisions.Add(d);
}
context.SaveChanges();
var teams = new Team[]
{
new Team { Id = Guid.NewGuid(), Name = "Team 1", Country = "Country 1", Flag = "flag_url_1", Payment = DateTime.Now, DivisionId = divisions[0].Id },
new Team { Id = Guid.NewGuid(), Name = "Team 2", Country = "Country 2", Flag = "flag_url_2", Payment = DateTime.Now, DivisionId = divisions[1].Id }
};
foreach (var t in teams)
{
context.Teams.Add(t);
}
context.SaveChanges();
}
}
}
}
Pages/Shared/_Layout.cshtml:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - FavoriteTeams</title>
@* <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" /> *@
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/FavoriteTeams.styles.css" asp-append-version="true" />
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.2.0/css/bootstrap.min.css" />
<!-- DataTables CSS -->
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css" />
<!-- Font Awesome CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-page="/Index">FavoriteTeams</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2024 - FavoriteTeams - <a asp-area="" asp-page="/Privacy">Privacy</a>
</div>
</footer>
@* <script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script> *@
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- Bootstrap JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.0/js/bootstrap.bundle.min.js"></script>
<!-- DataTables JS -->
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
Pages/Teams.cshtml:
@page
@model FavoriteTeams.Pages.TeamsModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
Layout = "_Layout";
}
<div class="eigentabel">
<h3 class="text-end">Teams Overview</h3>
@foreach (var division in Model.Divisions)
{
<span><h2>@division.Name </h2></span>
<table id="teamsTable-@division.Id" class="display">
<thead>
<tr>
<th style="width: 2%">#</th>
<th style="text-align: center; width: 2%"></th>
<th style="text-align: left; width: 10%">Team name</th>
<th style="width: 5%">Country</th>
<th style="width: 5%">Payed on</th>
<th style="width: 5%">Like</th>
</tr>
</thead>
<tbody>
@{
var num = 0;
}
@foreach (var team in Model.Teams.Where(t => t.DivisionId == division.Id))
{
<tr>
<td>@(++num)</td>
<td><img src="https://@team.Flag" width="20" height="13"></td>
<td>@team.Name</td>
<td>@team.Country</td>
<td>@(team.Payment.HasValue ? team.Payment.Value.ToString("dd-MMM-yyyy") : "-")</td>
<td><i onclick="toggleFavorite('@team.Id', this)" class="fa fa-heart-o heart-icon" data-team-id="@team.Id"></i></td>
</tr>
}
</tbody>
</table>
}
</div>
@section Scripts {
<script type="text/javascript">
function toggleFavorite(teamId, element) {
const favorites = JSON.parse(localStorage.getItem('favoriteTeams')) || [];
const index = favorites.indexOf(teamId);
if (index === -1) {
favorites.push(teamId);
element.classList.remove("fa-heart-o");
element.classList.add("fa-heart");
} else {
favorites.splice(index, 1);
element.classList.remove("fa-heart");
element.classList.add("fa-heart-o");
}
localStorage.setItem('favoriteTeams', JSON.stringify(favorites));
}
document.addEventListener("DOMContentLoaded", function () {
const favorites = JSON.parse(localStorage.getItem('favoriteTeams')) || [];
const icons = document.querySelectorAll('.heart-icon');
icons.forEach(icon => {
const teamId = icon.getAttribute('data-team-id');
if (favorites.includes(teamId)) {
icon.classList.remove('fa-heart-o');
icon.classList.add('fa-heart');
}
});
});
</script>
}
Teams.cshtml.cs:
using FavoriteTeams.Data;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
namespace FavoriteTeams.Pages
{
public class TeamsModel : PageModel
{
private readonly ApplicationDbContext _context;
public TeamsModel(ApplicationDbContext context)
{
_context = context;
}
public IList<Team> Teams { get; set; }
public IList<Division> Divisions { get; set; }
public async Task OnGetAsync()
{
Teams = await _context.Teams.Include(t => t.Division).ToListAsync();
Divisions = await _context.Divisions.ToListAsync();
}
}
}
Pages/FavoriteTeams.cshtml:
@page
@model FavoriteTeams.Pages.FavoriteTeamsModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
Layout = "_Layout";
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Favorite Teams</title>
</head>
<body>
<h1>Favorite Teams</h1>
<div id="favoriteTeamsContainer"></div>
</body>
</html>
@section Scripts {
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", () => {
const favorites = JSON.parse(localStorage.getItem('favoriteTeams')) || [];
console.log('Favorites from local storage:', favorites);
const allTeams = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.Teams));
console.log('All Teams:', allTeams);
// Log the structure of allTeams
console.log('Structure of allTeams:', JSON.stringify(allTeams, null, 2));
if (Array.isArray(allTeams)) {
favorites.forEach(favoriteId => {
console.log('Processing favorite teamId:', favoriteId);
const team = allTeams.find(t => {
console.log('Checking team:', t);
console.log('Favorite Team ID:', favoriteId);
if (t && t.Id) {
console.log('Current Team ID:', t.Id);
const idsMatch = t.Id.toLowerCase() === favoriteId.toLowerCase();
console.log('IDs match:', idsMatch);
return idsMatch;
} else {
console.error('Team or Team ID is undefined:', t);
return false;
}
});
console.log('Found team:', team);
if (team) {
const teamElement = document.createElement('div');
teamElement.innerHTML = `
<div>
<img src="https://${team.Flag}" width="20" height="13">
<a href="/Team_detail?varTeamId=${team.Id}">${team.Name}</a>
<span>${team.Country}</span>
<span>${team.Payment}</span>
</div>
`;
console.log('Appending team element to container:', teamElement);
document.getElementById('favoriteTeamsContainer').appendChild(teamElement);
} else {
console.error('Team not found:', favoriteId);
}
});
} else {
console.error('allTeams is not an array');
}
});
</script>
}
FavoriteTeams.cshtml.cs:
using FavoriteTeams.Data;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
namespace FavoriteTeams.Pages
{
public class FavoriteTeamsModel : PageModel
{
private readonly ApplicationDbContext _context;
public List<Team> Teams { get; set; }
public FavoriteTeamsModel(ApplicationDbContext context)
{
_context = context;
}
public void OnGet()
{
Teams = _context.Teams.Include(t => t.Division).ToList();
}
}
}
Program.cs:
using FavoriteTeams.Data;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddSession();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
SeedDatabase(app);
app.Run();
static void SeedDatabase(IApplicationBuilder app)
{
using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
{
DbInitializer.Initialize(serviceScope.ServiceProvider);
}
}