I have a couple extra }} showing in my Blazor web page screen. Is there somewhere I can put in my razor markup and it will tell me where mis-matched curly brackets are? I'm not seeing it when I look at the markup and everything builds ok.
I know in the past I've used various regex testers like this one .
I know I should just look at my code but my markup is very long and tough to trace through open/closed brackets.
I tried asking chatgpt.com, but it suggested searching for "}}" and nothing turned up. It also suggested it was after a certain section but that looked ok to me.
I can share my markup here in case someone sees the problem. I'm learning this for my work project and things are going great otherwise. I know the users will notice the issue.
This is above the @code section:
<h3>FTE PEOPLE</h3> <!-- Move expand/collapse buttons to start of flex container, push two halves to opposite sides so expand/collapse doesn't float above right panel ' --><div class="mb-3 d-flex align-items-center justify-content-between flex-wrap w-100"><!-- LEFT SECTION: Add / Edit / Delete + Expand / Collapse --><div class="d-flex align-items-center flex-wrap me-auto"><!-- Add/Edit/Delete --><button class="btn btn-success me-2" @onclick="AddPerson">Add</button><button class="btn btn-primary me-2" @onclick="EditPerson" disabled="@(!CanEditOrDelete)">Edit</button><button class="btn btn-danger me-3" @onclick="DeletePerson" disabled="@(!CanEditOrDelete)">Delete</button><!-- Expand / Collapse --><!-- Expand All Button --><!-- Use bootstrap icon for expand/collapse buttons with hover expand-all/collapse-all info --><button class="btn btn-outline-primary me-2" title="Expand All" @onclick="ExpandAll" disabled="@isExpandingAll"><i class="bi bi-arrows-expand"></i> @if (isExpandingAll) {<span class="spinner-border spinner-border-sm ms-2" role="status" aria-hidden="true"></span> }</button><!-- Collapse All Button --><button class="btn btn-outline-secondary" title="Collapse All" @onclick="CollapseAll" disabled="@isExpandingAll"><i class="bi bi-arrows-collapse"></i></button></div><!-- RIGHT SECTION: Review checkbox and note --><div class="d-flex align-items-center flex-wrap ms-auto"> @if (selectedPerson != null) {<InputCheckbox @bind-Value="IsReviewChecked" class="form-check-input" /><label class="form-check-label ms-2 me-3">Flag for Review</label> @if (selectedPerson.IsReviewItem == true) {<InputText @bind-Value="selectedPerson.Review" @onchange="OnReviewNoteChanged" class="form-control me-3" placeholder="Enter review note..." style="width: 250px;" /> } }</div></div><label for="yearFilter">Filter by Year:</label>@* <select class="form-select mb-3" @bind="selectedYear"> *@<select class="form-select w-auto mb-3 data-inline-block" @onchange="OnYearChanged"> @foreach (var year in availableYears) {<option value="@year.ToString()" selected="@(year == selectedYear ? "selected" : null)"> @year</option> }</select>@if (filteredReport is null || filteredReport.Count == 0){<div class="row"><div class="col-md-8"><p><em>No records for year @selectedYear.</em></p></div></div>}else{<div class="row"><!-- Left side: accordion --><div class="col-md-8"><div class="accordion" id="reportAccordion"> @foreach (var title in allTkTitles) { var isOpen = accordionStates.TryGetValue(title, out var open) && open; var collapseId = $"collapse-{title.GetHashCode()}"; // safe unique ID<div class="accordion-item mb-2"><h2 class="accordion-header" id="heading-@collapseId"><button class="accordion-button @(isOpen ? "" : "collapsed")" type="button" aria-expanded="@isOpen" aria-controls="@collapseId" @onclick="@(() => ToggleAccordion(title))"> @title</button></h2><div id="@collapseId" class="accordion-collapse collapse @(isOpen ? "show" : "")" aria-labelledby="heading-@collapseId" data-bs-parent="#reportAccordion"><div class="accordion-body p-2"> @if (groupedData.TryGetValue(title, out var groupPeople) && groupPeople != null) {<table class="table table-sm table-striped"><thead><tr><th>Select</th><th>isReview</th><th>FTE Whole</th><th>ID</th><th>Name</th><th>Loc</th><th>Hired</th><th>Termed</th><th>Department</th><th>Roles</th><th>Review Note</th><th>Actions</th></tr></thead><tbody> @foreach (var person in groupPeople.OrderBy(p => p.Name)) {<tr class="@(selectedPerson == person ? "table-primary" : "")"><td><input type="radio" name="selectedPerson" checked="@(selectedPerson == person)" @onchange="() => SelectPerson(person)" /></td> @*<td>@(Convert.ToInt32(person.IsReviewItem) == 1 ? "Yes" : "No")</td> *@<td> @if (person.IsReviewItem == true) {<i class="bi bi-flag-fill text-danger" title="Flagged for review"></i> } else {<span>-</span> }</td><td> @((person.ISFteWhole == true) ? "Yes" : "No") </td><td>@person.RefId</td><td>@person.Name</td><td>@person.Loc</td><td>@person.Hired?.ToShortDateString()</td><td>@person.Termed?.ToShortDateString()</td><td>@person.Department</td><td>@person.Roles</td><td>@person.Review</td><td><a class="btn btn-sm btn-primary" @onclick="EditPerson" disabled="@(!CanEditOrDelete)">Edit</a></td></tr> }</tbody></table> } else {<p><em>Loading data...</em></p> }</div></div></div> } @* foreach *@</div></div><!-- Right Side: Side Panel --><div class="col-md-4 border-start ps-3"> @if (selectedPersonSidePanel != null) {<!-- debug --><h5 class="mt-2">Roles for @selectedPersonSidePanel.Name (@selectedYear)</h5> @foreach (var role in allFteRoles .Where(r => r.RefID == selectedPersonSidePanel.RefId && r.ProdYear == selectedYear) .OrderByDescending(r => r.EditDt)) {<div class="mb-1"><button class="btn btn-outline-primary btn-sm w-100 text-start" @onclick="@(() => SelectRole(role))"> @role.PersonTitle (@role.TitleId)</button></div> } @if (selectedRole != null) {<div class="mt-3 border-top pt-3"><h6>Time in Role: @selectedRole.PersonTitle</h6><table class="table table-sm table-bordered"><thead><tr><th>Month</th><th>FTS</th><th>Reg</th><th>LOA</th><th>MTD FTE</th><th>YTD FTE</th><th>Note</th></tr></thead><tbody> @for (int month = 1; month <= 12; month++) { var m = month.ToString("D2"); var fts = GetProp<decimal?>(selectedRole, $"m{m}Fts"); var reg = GetProp<int?>(selectedRole, $"m{m}RegDays"); var loa = GetProp<int?>(selectedRole, $"m{m}LoaDays"); var mtd = GetProp<decimal?>(selectedRole, $"m{m}Fte"); @* populate from SP column m01Fte... *@ var ytd = GetProp<decimal?>(selectedRole, $"y{m}Fte"); @* populate from SP column y01Fte... *@ var note = GetProp<string>(selectedRole, $"m{m}Note");<tr><td>@CultureInfo.CurrentCulture.DateTimeFormat.GetAbbreviatedMonthName(month)</td><td>@fts</td><td>@reg</td><td>@loa</td><td>@(mtd?.ToString("0.0000") ?? "")</td><td>@(ytd?.ToString("0.0000") ?? "")</td><td>@note</td></tr> }</tbody></table><button class="btn btn-secondary btn-sm mt-2" @onclick="EditSelectedRole"> Edit Role</button></div> } }</div> @* md-4 *@</div> <!-- end row -->}I'm including screen shots of the top and bottom of my page so you can picture what the markup looks like.
