Razor页面@foreach循环SelectedVote仅填充首条记录问题求助
问题分析与解决方案
核心问题原因
- 重复DOM ID:在
foreach循环中,给SelectedVote、SimpleMajority等元素设置了固定ID,DOM中ID必须唯一,导致JS只能选中第一行元素,其余行无法更新。 - onchange事件触发时机误解:下拉框
onchange仅在用户手动选择选项时触发,页面初始化加载时不会自动执行,所以初始状态下SelectedVote无值。 - 单选按钮无事件绑定:未给ActiveVote的单选按钮添加点击事件,无法实现点击后将SelectedVote值填入对应列的需求。
分步解决方案
1. 修复前端重复ID问题,改用类名标识元素
修改表格行代码,移除重复ID,改用类名区分不同功能的元素,确保每行元素可被正确定位:
<tbody> @foreach (var obj in Model.WorkingVote.OrderBy(i => i.Municipality)) { <tr width="100%"> <td width="14%"> <div class="mb-3"> @Html.TextBoxFor(modelItem => obj.Municipality, new { disabled = "disabled", @readonly = "readonly", @class = "form-control", @style = "width: 125px" }) </div> </td> <td width="14%"> <div class="mb-3"> @Html.TextBoxFor(modelItem => obj.SupervisorName, new { disabled = "disabled", @readonly = "readonly", @class = "form-control", @style = "width: 175px" }) </div> </td> <td width="12%"> <div class="mb-3"> @Html.TextBoxFor(modelItem => obj.SimpleMajority, new { disabled = "disabled", @readonly = "readonly", @class = "form-control simple-majority", @dir = "rtl", @style = "width: 75px" }) </div> </td> <td width="12%"> <div class="mb-3"> @Html.TextBoxFor(modelItem => obj.TwoThirdsMajority, new { disabled = "disabled", @readonly = "readonly", @class = "form-control twothirds-majority", @dir = "rtl", @style = "width: 75px" }) </div> </td> <td width="12%"> <div class ="mb-3"> @Html.TextBoxFor(modelItem => obj.SelectedVote, new { disabled = "disabled", @readonly = "readonly", @class = "form-control selected-vote", @dir = "rtl", @style = "width: 100px" }) </div> </td> <td width="12%"> <div class="mb-3 active-vote"> <label> @Html.RadioButtonFor(modelItem => obj.ActiveVote, "Yes", new { @class = "vote-radio", data-target = "yes" }) <span>YES</span> </label> <label> @Html.RadioButtonFor(modelItem => obj.ActiveVote, "No", new { @class = "vote-radio", data-target = "no" }) <span>NO</span> </label> <label> @Html.RadioButtonFor(modelItem => obj.ActiveVote, "Abstain", new { @class = "vote-radio", data-target = "abstain" }) <span>ABSTAIN</span> </label> </div> </td> <td width="12%"> <div class="mb-3"> @Html.TextBoxFor(modelItem => obj.YesVote, new { @class = "form-control yes-vote", @dir = "rtl", @style = "width: 100px" }) </div> </td> <td width="12%"> <div class="mb-3"> @Html.TextBoxFor(modelItem => obj.NoVote, new { @class = "form-control no-vote", @dir = "rtl", @style = "width: 100px" }) </div> </td> <td width="12%"> <div class="mb-3"> @Html.TextBoxFor(modelItem => obj.AbsVote, new { @class = "form-control abstain-vote", @dir = "rtl", @style = "width: 100px" }) </div> </td> </tr> } </tbody>
2. 更新JS脚本,实现全局更新与单选按钮功能
修改脚本,完成三个核心功能:页面初始化时填充SelectedVote、下拉框变化时更新所有行、单选按钮点击时填充对应列:
@section Scripts { <script type="text/javascript"> $(document).ready(function () { // 页面加载时初始化所有行的SelectedVote updateAllSelectedVotes($("#VoteType").val()); // 绑定VoteType下拉框变化事件 $("#VoteType").on('change', function() { updateAllSelectedVotes($(this).val()); }); // 绑定单选按钮点击事件 $('.vote-radio').on('click', function() { const $row = $(this).closest('tr'); const selectedVote = $row.find('.selected-vote').val(); const target = $(this).data('target'); // 清空当前行所有投票输入框 $row.find('.yes-vote, .no-vote, .abstain-vote').val(''); // 将值填入对应列 if (target === 'yes') { $row.find('.yes-vote').val(selectedVote); } else if (target === 'no') { $row.find('.no-vote').val(selectedVote); } else if (target === 'abstain') { $row.find('.abstain-vote').val(selectedVote); } }); }); // 批量更新所有行的SelectedVote值 function updateAllSelectedVotes(votetype) { if (!votetype) return; $('tr').each(function() { const $row = $(this); let votes; if (votetype === "Simple Majority") { votes = parseFloat($row.find('.simple-majority').val()); } else { votes = parseFloat($row.find('.twothirds-majority').val()); } $row.find('.selected-vote').val(votes); }); } </script> <partial name="_ValidationScriptsPartial"/> }
3. 后端初始化SelectedVote(可选)
如果希望页面加载时SelectedVote直接有默认值,可在OnGetAsync中根据当前Vote的类型赋值:
public async Task OnGetAsync(int Id, int? pageIndex) { Vote = _db.Vote.Find(Id); DisplayCommitteeData = await _db.Committee.ToListAsync(); DisplayVoteTypeData = await _db.VoteType.ToListAsync(); DisplaySupervisorData = await _db.Supervisor.ToListAsync(); DisplayStatusData = await _db.Status.ToListAsync(); IQueryable<WorkingVote> workingVote = from x in _db.Supervisor join y in _db.Vote on x.Status equals y.SupervisorStatus select new WorkingVote { VoteId = y.VoteId, VoteCode = y.VoteCode, VoteDate = y.VoteDate, VoteDesc = y.VoteDesc, VoteType = y.VoteType, Committee = y.Committee, Municipality = x.Municipality, SupervisorName = x.DisplayName, SimpleMajority = x.Simple, TwoThirdsMajority = x.TwoThirds, // 根据当前VoteType设置默认SelectedVote SelectedVote = y.VoteType == "Simple Majority" ? x.Simple : x.TwoThirds, ActiveVote = y.ActiveVote }; int casesPerPage = 20; WorkingVote = await PaginatedList<WorkingVote>.CreateAsync( workingVote, pageIndex ?? 1, casesPerPage); }
关键说明
- DOM唯一性:循环中禁止生成重复ID,改用类名或动态ID确保元素可被精准定位。
- 事件触发逻辑:页面加载需手动调用初始化函数,
onchange不会自动执行初始化操作。 - 行上下文定位:通过
closest('tr')获取当前操作的行,避免全局元素干扰。
内容的提问来源于stack exchange,提问作者MelB
相关产品推荐
相关产品推荐

