首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于id切换MVC表行的可见性

基于id切换MVC表行的可见性
EN

Stack Overflow用户
提问于 2013-06-15 23:51:36
回答 1查看 1.9K关注 0票数 1

在我的MVC Razor视图中,我有一个表,表中的行代表一个层次结构的两个级别。每一行都可以通过ajax调用加载一个局部视图内容区域。这可以很好地工作。

为了有一个更紧凑的列表,我现在想把这个表变成一个“轻量级的可折叠树形视图”。第二级中的行应仅在其标题行被单击时可见。当单击另一个标题行时,所有当前子行都应折叠/不可见,并展开新的子行集。

我主要是一个代码后台人员,不太习惯客户端脚本。我已经尝试了几种方法,但到目前为止还没有成功。我读了一些建议,但它们都略有不同,并不直接适用。这是我目前的尝试:

代码语言:javascript
复制
<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>&nbsp;</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?我看到许多人在类似的情况下使用class属性。class属性可以与纯整数值一起使用吗?

5)以我想要的方式切换行的最快方法是什么?循环所有行是不是太慢了?我将有10-20个标题行与2-10每个子行。

6)整个设计是不是很糟糕?我在MVC工具箱中没有找到treeview控件,因此我决定这样做。我认为这看起来至少和treeview一样好,但也许另一种方法会更好?

7) jQuery会有什么帮助吗?我在布局页面中包含了jQuery库,但我不知道如何使用它。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-06-16 03:41:16

像以前一样,表达一个详细的问题是非常清晰的。在稍微检查了一下之后,我意识到我错过了解析属性的语法。此示例现在完全正常工作:

代码语言:javascript
复制
<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;">&nbsp;</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属性。所以我把"itemprop“换成了"data-testSuiteId”。

5)可能有更快的方法,但这对我来说是可以接受的。

6)替代控制?

7)使用jQuery也可以做到这一点。这将使代码更紧凑,实际上也更快。

代码语言:javascript
复制
// 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();
};
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17125381

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档