在我的 MVC Razor View 中,我有一个表,其中的行代表层次结构的两个级别。可以通过 ajax 调用单击每一行来加载部分 View 内容区域。这工作得很好。
为了获得更紧凑的列表,我现在想将表格变成“轻型可折叠 TreeView ”。仅当单击标题行时,第二级中的行才应可见。单击另一个标题行时,所有当前子行应折叠/隐藏,并展开新的子行集。
我主要是一个代码隐藏人员,不太习惯客户端脚本编写。我尝试了多种方法,但到目前为止还没有成功。我读过一些建议,但它们都略有不同,并且不能直接适用。这是我目前的尝试:
<table style="width: 100%;">
<tr>
<td style="width: 30%; vertical-align: top;">
<table id="myTableTree" style="width: 100%;">
@foreach (var testSuite in Model.TestSuites)
{
<tr>
<th colspan="2" style="text-align: left;">
@Ajax.ActionLink(testSuite.Description, "GetContent", new { testSuiteId = testSuite.Id }, new AjaxOptions { UpdateTargetId = "subContent" }, new { onClick = "setShowState(" + testSuite.Id + ");" })
</th>
</tr>
foreach (var testCase in testSuite.TestCases)
{
<tr itemprop="@testSuite.Id" style="display: none;">
<td> </td>
<td>
@Ajax.ActionLink(testCase.Description, "GetContent", new { testCaseId = testCase.Id }, new AjaxOptions { UpdateTargetId = "subContent" })
</td>
</tr>
}
}
</table>
</td>
<td style="vertical-align: top;" id="subContent"></td>
</tr>
</table>
<script type="text/javascript">
function setShowState (testSuiteId)
{
var rows = document.getElementById('myTableTree').rows;
for (var i = 0; i < rows.length; i++)
{
var row = rows.item(i);
if (row.attributes['itemprop'] == testSuiteId)
row.style.display = 'block';
else
row.style.display = 'none';
}
};
</script>
如您所见,所有子行最初都设置为 display=none。我获取了一个任意属性来保存每个第二级行上的第一级 id。 itemprop 似乎和其他的一样好。在第一级行中,我添加了一个引用 JavaScript 函数的 onClick 调用。 setShowState 函数的目的是循环所有行并为行设置适当的可见性。当我检查生成的页面源时,它看起来像我预期的那样,但不起作用。子行永远不会扩展。
1) 设置初始服务器返回行 display=none 然后在客户端切换是否可以?
2) 让actionlink 触发ajax 服务器调用并触发客户端脚本来设置可见性是否可以?或者将 ajax 调用移至 java 脚本以仅进行一次调用会更好吗?
3) 使用display=block/none 或visibility=visible/collapse 进行切换是否更好?实际上会有什么区别吗?
4) 使用 itemprop 来存储父 id 可以吗?我看到许多人在类似的情况下使用类属性。类属性可以与纯整数值一起使用吗?
5)按照我想要的方式切换行的最快方法是什么?循环所有行是否太慢?我将有 10-20 个标题行,每行有 2-10 个子行。
6) 整个设计很糟糕吗?我在 MVC 工具箱中没有找到 TreeView 控件,因此我决定采用这种方式。我认为这看起来至少和 TreeView 一样漂亮,但也许另一种方法会更好?
7) jQuery 有什么帮助吗?我的布局页面中包含 jQuery 库,但我不知道如何使用它。
最佳答案
与之前很多次一样,表达一个详细的问题是非常清晰的。经过更多检查后,我意识到我只是错过了解析属性的语法。此示例现已完全运行:
<table style="width: 100%;">
<tr>
<td style="width: 30%; vertical-align: top;">
<table id="myTableTree" style="width: 100%;">
@foreach (var testSuite in Model.TestSuites)
{
<tr>
<th colspan="2" style="text-align: left; border: 0;">
@Ajax.ActionLink(testSuite.Description, "GetContent", new { testSuiteId = testSuite.Id }, new AjaxOptions { UpdateTargetId = "subContent" }, new { onClick = "setShowState(" + testSuite.Id + ");" })
</th>
</tr>
foreach (var testCase in testSuite.TestCases)
{
<tr data-testSuiteId="@testSuite.Id" style="visibility: collapse;">
<td style="width: 10%; border: 0;"> </td>
<td style="border: 0;">
@Ajax.ActionLink(testCase.Description, "GetContent", new { testCaseId = testCase.Id }, new AjaxOptions { UpdateTargetId = "subContent" })
</td>
</tr>
}
}
</table>
</td>
<td style="vertical-align: top;" id="subContent"></td>
</tr>
</table>
<script type="text/javascript">
// Toggle each section independantly
function setShowState(testSuiteId) {
var rows = document.querySelectorAll('[data-testSuiteId="' + testSuiteId + '"]');
for (var i = 0; i < rows.length; i++) {
var row = rows.item(i);
row.style.visibility = (row.style.visibility == 'visible') ? 'collapse' : 'visible';
}
};
// Alternative algorithm
// Always collapse previous section when a new one is selected
function setShowState2(testSuiteId) {
var rows = document.getElementById('myTableTree').rows;
for (var i = 0; i < rows.length; i++) {
var row = rows.item(i);
if (row.getAttribute('data-testSuiteId') == testSuiteId)
row.style.visibility = 'visible';
else if (row.getAttribute('data-testSuiteId') != null)
row.style.visibility = 'collapse';
}
};
</script>
我对我自己的问题提出以下建议:
1)是的,设置属性然后在客户端切换是完全可以的。
2) 是的,触发一个服务器端操作并同时触发一个客户端似乎没问题。
3)我试过了。就我而言,它似乎在显示和可见性方面都工作得同样好。通过进一步阅读,我了解到大多数情况下都会使用显示,但表格中的可见性稍好一些,因为不需要重新计算大小等表格属性。
4) itemprop 属性有效。但在 HTML5 中建议使用 data 属性。所以我用“data-testSuiteId”交换了“itemprop”。
5)可能有更快的方法,但这看起来对我来说可以接受。
6) 替代控制?
7) 使用 jQuery 也可以完成同样的任务。这将使代码更加紧凑,实际上也更快。
// Toggle section
function setShowState(testSuiteId) {
$("[data-testSuiteId='" + testSuiteId + "']").toggle();
};
// Display one section and collapse all others
function setShowState(testSuiteId) {
$("[data-testSuiteId]").hide();
$("[data-testSuiteId='" + testSuiteId + "']").show();
};
关于javascript - 根据 id 切换 MVC 表行的可见性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17125381/