DOM Bootstrap 模态框在局部视图中的位置

DOM placement of Bootstrap modals in Partial Views

我有一个触发模式的按钮元素。这段代码是可重用的,需要出现在许多不同的视图上。

<button class="btn btn-default" type="button" data-toggle="modal" data-target="#modalAcctToggle">
    Toggle Accounts
</button>

<div id="modalAcctToggle" tabindex="-1" class="modal fade">
    <div class="modal-dialog modal-sm">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
                <h4 class="modal-title">Available Accounts</h4>
            </div>
            <div class="modal-body">
                [contents not relevant]
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
            </div>
        </div>
    </div>
</div>

非常简单明了。将所有这些放在局部视图中,并根据需要使用 @Html.Partial("_accountToggler")

进行渲染

但是,Bootstrap 文档鼓励将模态框放置在页面的主体之外:

http://getbootstrap.com/javascript/#modals

Modal markup placement Always try to place a modal's HTML code in a top-level position in your document to avoid other components affecting the modal's appearance and/or functionality.

我的直接想法是为此使用 Razor 部分。

<button data-target="#modalAcctToggle" etc... />
@section modals {
    <div id="modalAcctToggle" etc... />
}

将所有模态框包裹在一个部分中,然后在布局中使用@RenderSection("modals"),模态框将在 DOM.

中的安全位置发出

不幸的是,Razor 部分在分部视图中不起作用!这显然是设计使然,但它是为了限制脚本在 partials 中的使用。

我发现人们提出了许多其他问题,他们试图解决部分部分中缺少部分的问题,但他们只关注处理脚本。在那里找到的解决方案基本上包括将您自己的等价物滚动到 Razor 部分,或者专门用于处理脚本(如捆绑)。当我的使用不是所述限制的目标时,必须努力重新发明 Razor 部分以绕过故意限制似乎很可笑。

我怎样才能最好地处理将模态 HTML 放到不同的位置?

更新: 正如在对答案的评论中所讨论的,这个问题是基于两个基本的误解。

1) Bootstrap 模态可以毫无问题地位于 HTML 的其余部分之中。您只需要小心防止它继承任何 CSS 它不应该继承的内容。

2) 章节不累积。所以即使我可以在部分视图中使用部分,它也不会按照我想要的方式工作。使用同一部分的多个部分会相互覆盖。这可能是部分在设计上无法在部分中工作的真正原因。

TL;DR; 这里的关键要点是 布局 中定义了 部分] 看法;它们大致相当于您在 WebForms 项目中找到的 ContentPlaceholder 控件。然后将它们用于 "full" 视图中,这些视图通常对应于您的各种操作。如果你还没有读过,我想说 Scott Gu's intro to sections 有很好的解释。


如果我们假设您有这个部分视图,我将其称为 _Modal.cshtml:

<button class="btn btn-default" type="button" data-toggle="modal" data-target="#modalAcctToggle">
    Toggle Accounts
</button>

<div id="modalAcctToggle" tabindex="-1" class="modal fade">
    <div class="modal-dialog modal-sm">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
                <h4 class="modal-title">Available Accounts</h4>
            </div>
            <div class="modal-body">
                [contents not relevant]
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
            </div>
        </div>
    </div>
</div>

并且您的布局类似于

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - My ASP.NET Application</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")

</head>
<body>
    @RenderSection("modals", required: false)

    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
        </footer>
    </div>

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")

    @RenderSection("scripts", required: false)
</body>
</html>

可以做这样的事情,比如说,Index.cshtml

@section modals
{
    @Html.Partial("_Modal")
}

它会在正确的位置发出正确的标记。然后,您需要将任何交互逻辑直接放在父视图中,或使用 scripts 部分(在父视图中)。