DOM placement of Bootstrap modals in Partial Views - asp.net-mvc

I have a button element that triggers a modal. This piece of code is reusable, and needs to be present on many different 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>×</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>
Pretty simple and straightforward. Put all that in a partial view, and render it as necessary with #Html.Partial("_accountToggler")
However, Bootstrap documentation encourages placing modals outside of the meat of the page:
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.
My immediate thought was to use Razor sections for this.
<button data-target="#modalAcctToggle" etc... />
#section modals {
<div id="modalAcctToggle" etc... />
}
Wrap all modals in a section, then use #RenderSection("modals") in the Layout, and the modals would be emitted at a safe place in the DOM.
Unfortunately, Razor sections do not work in Partial Views! This is apparently by design, but it is meant to limit the use of scripts in partials.
I have found many other questions from people trying to work around the lack of sections in partials, but their exclusive focus is on dealing with scripts. The solutions found there essentially consist of rolling your own equivalent to Razor sections, or are specialized for dealing with scripts (like bundling). It seems ludicrous to have to put in the effort of reinventing Razor sections to hack around an intentional limitation when my usage is not the target of said limitation.
How can I best handle getting the modal HTML into a different spot?
UPDATE: As discussed in the comments on the answer, this question was based in two fundamental misunderstandings.
1) Bootstrap modals can be located amongst the rest of the HTML without issue. You just have to be careful to keep it from inheriting any CSS it shouldn't.
2) Sections are not cumulative. So even if I could use sections in partial views, it would not work the way I want it to. Multiple partials using the same section would overwrite each other. This is likely the real reason why, by design, sections do not work in partials.

TL;DR; The key takeaway here is that sections are defined in the layout view; they're roughly equivalent to the ContentPlaceholder controls you'd find in a WebForms project. They are then used in the "full" views that normally correspond to your various actions. If you haven't read it yet, I'd say Scott Gu's intro to sections has a good explanation.
If we assume that you have this partial view, which I'll call _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>×</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>
And you have a layout similar to
<!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>© #DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
</body>
</html>
The you can do something like this in, say, Index.cshtml
#section modals
{
#Html.Partial("_Modal")
}
and it will emit the proper markup in the correct place. You would then need to place any interaction logic either directly in the parent view, or use the scripts section (in the parent view).

Related

How to create sub menu items in left navigation menu?

I will be creating left vertical (sidebar) navigation menu by referring "Example" in https://getbootstrap.com/docs/5.0/components/accordion/.
Below is the link where sub menu items are present as Subitem 1, Subitem 2, Subitem 3 under item 3 and item 4.
https://www.codeply.com/go/K1gXPZwV59/bootstrap-vertical-sidebar-_-accordion-menu-with-submenus
Could you please help how to create such sub menu items(Subitem 1, Subitem 2, Subitem 3) in the "Example"?
Do you want nested accordions? If so, just nest them. Snippet below uses the "Example" you referred to in your question.
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
<div class="accordion" id="accordionExample">
<div class="accordion-item">
<h2 class="accordion-header" id="headingOne">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne"> Accordion Item #1 </button>
</h2>
<div id="collapseOne" class="accordion-collapse collapse" aria-labelledby="headingOne" data-bs-parent="#accordionExample">
<div class="accordion-body">
<strong>This is the first item's accordion body.</strong> It is shown by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow. </div>
<div class="accordion" id="accordionExampleTwo">
<div class="accordion-item">
<h2 class="accordion-header" id="headingOneOne">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOneOne" aria-expanded="true" aria-controls="collapseOneOne"> Accordion Item #1-1 </button>
</h2>
<div id="collapseOneOne" class="accordion-collapse collapse" aria-labelledby="headingOneOne" data-bs-parent="#accordionExampleTwo">
<div class="accordion-body">
<strong>This is the first NESTED item's accordion body.</strong> It is shown by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow. </div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="headingOneTwo">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOneTwo" aria-expanded="true" aria-controls="collapseOneTwo"> Accordion Item #1-2 </button>
</h2>
<div id="collapseOneTwo" class="accordion-collapse collapse" aria-labelledby="headingOneTwo" data-bs-parent="#accordionExampleTwo">
<div class="accordion-body">
<strong>This is the second NESTED item's accordion body.</strong> It is shown by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow. </div>
</div>
</div>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="headingTwo">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"> Accordion Item #2 </button>
</h2>
<div id="collapseTwo" class="accordion-collapse collapse" aria-labelledby="headingTwo" data-bs-parent="#accordionExample">
<div class="accordion-body">
<strong>This is the second item's accordion body.</strong> It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow. </div>
</div>
</div>
</div>
If you want a list group menu inside the accordion:
.accordion-body {
/*padding: 0 !important;*/
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
<!--- Bootstrap Icons -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons#1.10.2/font/bootstrap-icons.css">
<div class="accordion" id="accordionExample">
<div class="accordion-item">
<h2 class="accordion-header" id="headingOne">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
Accordion Item #1
</button>
</h2>
<div id="collapseOne" class="accordion-collapse collapse" aria-labelledby="headingOne" data-bs-parent="#accordionExample">
<div class="accordion-body">
<div class="list-group">
The current link item <i class="bi bi-caret-down-fill"></i>
<div class="collapse" id="listCollapseOne">
A nested first link item
A nested second link item
A nested third link item
</div>
A second link item
A third link item
A fourth link item
</div>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="headingTwo">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
Accordion Item #2
</button>
</h2>
<div id="collapseTwo" class="accordion-collapse collapse" aria-labelledby="headingTwo" data-bs-parent="#accordionExample">
<div class="accordion-body">
<strong>This is the second item's accordion body.</strong> It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing
and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow.
</div>
</div>
</div>
</div>

Bootstrap 5 Modal Is Not Showing Dialog

I am completely new to Bootstrap and am trying to work it into an existing jQuery project. I can't seem to get modals to work. I have the following markup from the Bootstrap example at the bottom of my page:
<div class="modal" tabindex="-1" id="message_area">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modal title</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>Modal body text goes here.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
My Javascript code is:
$("#message_area").modal();
There are no Javascript errors yet no dialog box pops up. I'm sure I'm missing something.
I stripped down my code to just include jQuery and Bootstrap JS and CSS. Using the example from Bootstrap model page, I still can't get it to work. My stripped down code is:
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script src="http://dev.adex-intl.com/adex/clientsSite/public/js/jquery.js"></script>
<script src="http://dev.adex-intl.com/adex/clientsSite/public/js/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<link href="http://dev.adex-intl.com/adex/clientsSite/public/css/node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
<title>Orders** DEVELOPMENT SITE **</title>
</head>
<body>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#message_area">
Launch demo modal
</button>
<div class="modal" tabindex="-1" id="message_area" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modal title</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>Modal body text goes here.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</body>
</html>
Beware of the difference between Bootstrap 4 and bootstrap 5:
You are stating that you use Bootstrap 5, but the toggle and target attributes you use in your button are Bootstrap 4 style.
Replace data-toggle by data-bs-toogle
and data-target by data-bs-target
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#message_area">
Your html page displays the modal correctly once this is fixed, as you can see here (jsfiddle.net). In this example, Bootstrap and JQuery are retrieved via CDN, in order to be sure that the right code is retrieved.
Check the documentations
https://getbootstrap.com/docs/4.6/components/modal/
https://getbootstrap.com/docs/5.0/components/modal/
Also, the placement of your script elements might not be optimal.
See Bootstrap recommendation: https://getbootstrap.com/docs/5.0/getting-started/introduction/#js

Bootstrap modal nonfunctional in rails

(I know there's a bunch of questions like this, but none seem to answer my specific situation.)
I'm trying to get a bootstrap modal to display in a Rails view, but the associated button simply does nothing - clicking it has no effect at all beyond the button interaction effect. As far as I know bootstrap in general is set up to work properly; that doesn't seem to be my issue.
Modal html, most of which is directly copied from the bootstrap documentation:
<div id="new_event">
<button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#new-event-modal">+</button>
<div id="new-event-modal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">add an event!</h4>
</div>
<div class="modal-body">
Text! <!--form goes here -->
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">cancel</button>
</div>
</div>
</div>
</div>
</div>
My custom.scss has #import "bootstrap-sprockets"; #import "bootstrap", and my application.js has //= require bootstrap-sprockets. Other javascript things are working perfectly well, and other bootstrap things are working perfectly well. What am I missing here?
That is not going to work. If you are using Rails 6, there is a very specific way to add Bootstrap to your rails app. I have described it on github:
https://github.com/overdrivemachines/bootstrap-rails

How do I change an Angular UI Bootstrap panel color when the panel is open

I need to change the panel color of the parent that is open. I was told I could use something called "panel-class" but my attempts to use if have been unsuccessful. I copied the sample code directly from the "example" that was provided but still the panel color does not change. I am trying to use this in an MVC _Layout.cshtml page. Could that be the reason?
Here is my HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>#ViewBag.Title</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
#Scripts.Render("~/bundles/jquery")
<link href="~/Content/bootstrap.css" rel="stylesheet" />
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/angular-sanitize.js"></script>
<script src="~/Scripts/ui-bootstrap-custom-tpls-0.13.3.js"></script>
<script src="~/Scripts/app/app.js"></script>
<script src="~/Scripts/app/AccordionCtrl.js"></script>
<script src="~/Scripts/app/generalsearchService.js"></script>
</head>
<body>
<header>
<div class="content-wrapper">
<div class="float-left">
<p class="site-title">
</div>
<div class="float-right">
<nav>
</nav>
</div>
</div>
</header>
<div>
</div>
<div ng-app="myModule" ng-controller="AccordionCtrl">
<script type="text/ng-template" id="group-template.html">
<div class="panel {{panelClass || 'panel-default'}}">
<div class="panel-heading">
<h4 class="panel-title" style="color:#fa39c3">
<a href tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" accordion-transclude="heading">
<span ng-class="{'text-muted': isDisabled}">{{heading}}</span>
</a>
</h4>
</div>
<div class="panel-collapse collapse" collapse="!isOpen">
<div class="panel-body" style="text-align: right" ng-transclude></div>
</div>
</div>
</script>
<p>
<button type="button" class="btn btn-default btn-sm" ng-click="status.open = !status.open">Toggle last panel</button>
<button type="button" class="btn btn-default btn-sm" ng-click="status.isFirstDisabled = ! status.isFirstDisabled">Enable / Disable first panel</button>
</p>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="oneAtATime">
Open only one at a time
</label>
</div>
<accordion close-others="oneAtATime">
<accordion-group heading="Static Header, initially expanded" is-open="status.isFirstOpen" is-disabled="status.isFirstDisabled">
This content is straight in the template.
</accordion-group>
<accordion-group heading="{{group.title}}" ng-repeat="group in groups">
{{group.content}}
</accordion-group>
<accordion-group heading="Dynamic Body Content">
<p>The body of the accordion group grows to fit the contents</p>
<button type="button" class="btn btn-default btn-sm" ng-click="addItem()">Add Item</button>
<div ng-repeat="item in items">{{item}}</div>
</accordion-group>
<accordion-group heading="Custom template" template-url="group-template.html">
Hello
</accordion-group>
<accordion-group heading="Delete account" panel-class="panel-danger">
<p>Please, to delete your account, click the button below</p>
<button class="btn btn-danger">Delete</button>
</accordion-group>
<accordion-group is-open="status.open">
<accordion-heading>
I can have markup, too! <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': status.open, 'glyphicon-chevron-right': !status.open}"></i>
</accordion-heading>
This is just some content to illustrate fancy headings.
</accordion-group>
</accordion>
</div>
<div id="myBody" style="margin-top:50px; margin-left:320px; width:80%; position:absolute">
#RenderBody()
</div>
</div>
#Scripts.Render("~/bundles/jquery")
#RenderSection("scripts", required: false)
</body>
</html>
Here is what it looks like when I run it:
As you can see, the text color changes on the one example, but the panel color does not change on the "Delete" tab. Thanks in advance for any assistance. Have a great day all!
I have the answer for you, check out my github page:
https://github.com/brendancopley/customDirectives/tree/master/custom-accordion-ui-bootstrap
Here's the example DEMO https://brendancopley.github.io/customDirectives/custom-accordion-ui-bootstrap/
I made a Custom Directive of UI-Bootstrap Accordion.
To answer your question, it's really simple:
.panel.panel-open {
color: orangered
}
Or you can add an id to your uib-accordion-group and then include it in the css to have different color when opened for each heading you want.
<div uib-accordion-group id="anything" class="panel-white" is-open='menuStatus[2].isOpen'>
<uib-accordion-heading>
<i style="padding-right:10px;" class="pull-left glyphicon" ng-class="{'glyphicon-chevron-down': menuStatus[2].isOpen, 'glyphicon-chevron-up': !menuStatus[2].isOpen}"></i>Example Heading
</uib-accordion-heading>
<p>blah blah blah blah</p>
</div>
And then in your CSS add this
#anything.panel.panel-open {
color: #8f42f4; }
Per the examples here, you can see that the Delete account accordion uses the panel-class attribute to change/override the default class and the I can have markup, too! accordion shows how to use ng-class to set a class based on whether or not the accordion is open.
Either open the Plunker from this example or fork it and change the panel-class attribute from panel-danger to panel-success to see the change. Additionally, you can change the glyphicon-chevron-down and glyphicon-chevron-right classes to your own custom classes and they will get applied on open or close.
In the future, please read the documentation and examples thoroughly before asking for help. Per SO's own guidelines, show that you've attempted to solve the issue before asking for help.

Bootstrap 3 modals not working on Rails 4

I am using twitter bootstrap 3 for my project but cannot seem to get the modals to work correctly when loading remote content.
My "application" layout is the following:
<!DOCTYPE html>
<html>
<head>
<title>TestBootstrap</title>
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
</head>
<body>
<%= yield %>
</body>
</html>
I have two views, one is index and the other is show
index contains the following information:
<!-- Button trigger modal -->
<a data-toggle="modal" href="#myModal" class="btn btn-primary btn-lg">Launch demo modal</a>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" data-remote="/modal/show">
<div class="modal-dialog">
<div class="modal-content">
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
Show contains the following:
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Modal title</h4>
</div>
<div class="modal-body">
<p>Find me in app/views/modal/show.html.erb</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
For some odd reason I get the modal displayed without a background when adding the "remote-data" attribute.
I have tried removing "turbo_links" but it has been futile. This only seem to happen in rails though, as I have tried a similar example in jsfiddle and it works fine!
Please see http://jsfiddle.net/6X2zb/
Please help and thanks in advance !
I hit this wall just yesterday. I wound up using bootstrap-modal instead, which provides a patch for bootstrap 3.
https://github.com/jschr/bootstrap-modal
Bootstrap 3 specific examples:
http://jschr.github.io/bootstrap-modal/bs3.html
Here's the rails example
https://github.com/jschr/bootstrap-modal/wiki/Ruby-on-Rails----AJAX-Modal-Example
I was finally able to figure out what the issue was from Bootstrap 3 with remote Modal
Turns out I was missing the surrounding
<div class="modal-dialog">
<div class="modal-content">
... contents ...
</div>
</div>

Resources