Bootstrap Modals misbehaving - html

I'm trying to add a BootStrap modal to an already-existing page and I'm running into the following problem:
The modal displays exactly as I would expect it to, content in place looking quite beautiful but I have two problems. If I specify only class="modal" the modal displays by default when the page loads and will not close. If I include class="modal hide" then the modal does not display at page load but also doesn't close when the appropriate buttons are clicked.
I'm not making any big departures from the modals sample code on the Bootstrap site, any ideas what's going wrong?
Here's the button that's supposed to launch the modal:
<a class="btn" data-toggle="modal" href="#testmodal" >About</a>
And here's the modal itself:
<div class="modal hide fade in" id="testmodal">
<div class="modal-header">
<button class="close" data-dismiss="modal">x</button>
<h3>Modal Header</h3>
</div>
<div class="modal-body">
<p>body</p>
</div>
<div class="modal-footer">
Close
</div>
</div>
And for the record, yes I did remember to include bootstrap-modal.js and bootstrap-transition.js

Glad your problem is resolved.
Also if you want the default bootstrap functionality without customizing anything just use the big download button on the main page. This zip file contains a default bootstrap.min.js file that includes all the plugins (like the modal dialogs etc). If you use that one instead of all the seperate javascript files your page has to make less requests and load faster.

your close link should be like this:
<a class="close" data-dismiss="modal">×</a>
since, data-dismiss is a custom HTML5 data attribute. Here it is used to close the modal window.

Related

How to avoid bootstrap modal disappearance when auto postback in asp.net

Am using vb.net in my asp.net project also bootstrap 4. I have two dropdown list inside a modal, when the user select an item from the first dropdown list, the second list will be sorted.
The problem is, when the user select from the first list the page will postback which casing the modal to disappear. I tried to use <asp:UpdatePanel></asp:UpdatePanel> tag, but it didn't work.
I would appreciate any help or suggestions! Here's my code:
<div class="modal fade" id="AddNew" data-backdrop="static" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Add New</h4>
</div>
<div class="modal-body">
<div class="row pb-3">
<div class="col-lg-6">
<asp:DropDownList ID="DropDownList1" class="browser-default custom-select form-control-sm" runat="server" AutoPostBack="true"></asp:DropDownList>
</div>
<div class="col-lg-6">
<asp:DropDownList ID="DropDownList2" class="browser-default custom-select form-control-sm" runat="server"></asp:DropDownList>
</div>
</div>
<div class="row">
<div class="col-lg-6">
<div class="input-group mb-3 input-group-sm">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-user"></i></span>
</div>
<asp:TextBox ID="TextBoxName" class="form-control" runat="server" placeholder="User Name..."></asp:TextBox>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6">
<asp:DropDownList ID="DropDownListGroup" class="browser-default custom-select form-control-sm" runat="server"></asp:DropDownList>
</div>
</div>
</div>
<div class="modal-footer">
<asp:Button ID="ButtonAdd" class="btn btn-primary btn-sm" runat="server" Text="Add" />
</div>
</div>
</div>
</div>
There is not much you can do here. A post back will blow out a jQuery.UI dialog, a ajaxtoolkit popup, and of course a bootstrap dialog.
This means and suggests that while you can pop a dialog and let a user choose or click on something? That action can be though as ALSO the means to close that dialog if the user choice is to cause a post-back (saves you having to write code to close the dialog!!!).
If you need something like a cascade combo box?
Then I would NOT use a popup, but simply use a update panel, and display the several objects.
If you really want the cascade combo box or whatever in the popup? Then you have to use JavaScript and ajax calls to the web page - no post backs allowed. You CAN do this, but it quite a bit of extra work. So, I would suggest that you avoid the popup for such kinds of work, since you not only lose the GREAT nice easy to use button code stubs and code behind (the reason why asp.net and web forms are oh so easy to use!!!).
So, you have to get say a little bit creative. You can put all the options say inside of a "div" section, and hide or show that section with code behind.
And then show/hide the area on the form with say this:
myDiv.Style("Display") = "normal"
So hide/show a area on the form. Thus in that panel, we can have two combo boxes (choose state/province and then cascade to the city choice). When the user selects a city, (and auto postback) then we shove that selecting into the text box, and hide the div. All works with just a few lines of code, and no jQuery or bootstrap dialogs.
So the general rule?
Pop a dialog - user can enter data, check box a few things, enter comments and then they hit ok button or whatever. But that button will do a post-back and will close the dialog. So that is the design pattern.
If you break from above? Then you can build dialog forms, but you have to wire up any actions of that dialog as ajax calls. A post back causes the WHOLE browser page to travel up to server. Code behind runs, changes anything on that page and then the whole page travels back down to client and THEN is re-displayed. I should ALSO add that the web server page is now gone, does NOT exist server side and all variables in code etc. are also gone.
The code behind NEVER interacts with the user. it ONLY interacts with the web page in that round trip and ONLY during the short time that the page is up on the server, and code behind runs. So a post back will blow out any JavaScript running on that page, since the whole page travels up to server, code behind runs, and WHOLE page THEN travels back down to client, the browser loads the page AND THEN STARTS RUNNING the JavaScript. Since a post back sends the page to the server and THEN will send the WHOLE page back, then you can't have a post-back run and keep your JavaScript popus etc. running, and worse the browser re-loads the whole page, and the JavaScript code STARTS over running again!!!
So if you really want to do this? Then you have to make ajax calls.
So the rule and design pattern? A post-back is to close the dialog and you only can have or allow one post-back as the "final" action of that dialog. Break this rule, and you then having to hand code up a LOT of JavaScript and ajax calls.
So the answer is you can't do a post back. You can do this with jQuery.ui dialogs and insert a iframe into the dialog. So you put the asp.net web page and buttons inside of a iframe - but then again, that popup in MOST cases will want to interact with the current page and a iframe does not let you do this for all practical use cases anyway.
I have thus found by changing my design patterns and assumptions, then you simply have to cook up slightly different approaches to your UI designs, and thus once done, then you can do this.
So, for example, you might pop one list to select from, and then when the user selects a value (post back) you then say perhaps popup another list for the user to select. So you can pop a list for display, and the user selection of course can be a post-back (and often it will be). Then code behind can trigger another dialog and you get that input.

Angular - two the same ng-template with component in one HTML file (How to make reference, not copy)

I have the following problem: I create a web application using Angular. I am making a search form that has several fields. I have it ready as a component. Code below:
<ng-template #filter>
<app-articles-filter #articlesFilterDesktop
(onFilterFormSubmit)="submitFilterForm()"
[categories]="categories"></app-articles-filter>
</ng-template>
To put this code on the page, I'm using ng-container: <ng-container *ngTemplateOutlet = "filter"> </ng-container>. By default, the search form is at the top of the page. I also wanted to do so that when the user resize the window (mobile devices), a button will appear in the place of the search form. After clicking on this button a modal window with this search form would appear. Modal window code (I'm using Bootstrap):
<div class="modal fade" id="filterArticlesModal" tabindex="-1" role="dialog" aria-labelledby="filterArticlesModalTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<ng-container *ngTemplateOutlet="filter"></ng-container>
</div>
</div>
</div>
</div>
Having the same component twice with ng-template in one HTML file, I get a warning in the console:
"Found 2 elements with non-unique id [duplicated id here]: [html from search form here]".
The fields completed in the search form are not automatically completed in the modal view. (When I complete the form on the page, narrow the browser window and open the modal window.. there are empty fields in the modal window and vice versa). As I understand it, Angular just pastes the code and that's it. Is it possible to somehow treat this code fragment (my search form component) as one reference and not a copy?
EDIT:
I'm not sure about the duplicate ID fiasco. You could remove id's and just go off of classes, or maybe have some property from the component added in to the ID that you can control: id="searchBar{{foo}}"?
Solving the data consistency when you switch between searches can definitely be done.
If you want to have the search value act as a singleton I recommend putting that value in a service, and referencing it from the components. This can be done a few different ways, and there is one thing to consider:
Do you want the search to persist after the page in navigated to/from? If yes then keep the service that stores the search global, if not define it in the providers: [] property of the component that houses these search components (that way it gets deleted each time the component is destroyed)

JAWS reads Headings as clickable even though parent div has not click handler associated

I am working on accessibility testing for an Angular project. I have some code for a modal that is as below
<div class="modal fade" bsModal #cancelConfirmModal="bs-modal" tabindex="-1" role="dialog"
attr.aria-label="Cancel Modal" aria-hidden="true">
<div class="md-dialog modal-md">
<!-- Modal content-->
<div class="md-content">
<div class="md-header">
<div class="md-title pull-left">
<h4 tabindex=0 class="headerBottomMarginNone"> Cancel</h4>
</div>
<button type="button" class="close-popup" (click)="hideCancelModal()">
<img src="{{ pathImg }}/close.png" alt="Close Icon"
(mouseover)="changeCloseIconOnHover('close-popup3')"
(mouseout)="changeCloseIcon('close-popup3')" id="close-popup3">
<label class="sr-only">Close</label>
</button>
</div>
<div tabindex=0 class="md-body">
{{ cancelMessageBody }}
</div>
<div class="md-footer">
<button type="reset pull-right" class="ts-btn ts-btn-primary no-btm-margin" (click)="revert()">Yes</button>
<button type="pull-right" (click)="hideCancelModal()"
class="ts-btn ts-btn-tertiary margin-left10 no-btm-margin">Cancel</button>
</div>
</div>
</div>
</div>
When I tab over to <h4 tabindex=0 class="headerBottomMarginNone"> Cancel</h4> it reads Cancel heading level 4 clickable. There is no click event on the parent or even its parent. h4 is made tab reachable as per the QA's preference. How do I stop JAWS from announcing clickable??
Short Answer
Remove the tabindex.
Long Answer
Headings should not have a tabindex (other than maybe a tabindex="-1", covered below).
Anything with a tabindex is considered to be interactive and it is expected that you have supplied the relevant handlers for focus, click, keyboard keys etc.
Your QA is incorrect on this and is making the software harder to use.
The only time it is appropriate to use a tabindex on a heading is if you need to programatically focus it (for example on an AJAX application where you load a new page in it is a good practice to focus the heading level 1 on the page to let screen reader users know the new page has loaded in.) At this point the only tabindex that is appropriate is tabindex="-1" so that it can only be focused programatically and not via the tab key.
Your QA may think that screen reader users need to be able to focus the headings, this is not the case! They use shortcut keys within their screen reader to access headings on the page.
Also remove it from <div tabindex=0 class="md-body"> as that is also not interactive.
Finally it is likely you do not need tabindex="-1" on the modal itself as when you open the modal you should focus either the first interactive element or the close button (which in your case appears to be the cancel button anyway.), however there may be functionality in your software that I am not aware of so that is just a point to consider.

Materialize Modal not working, staying open

I'm trying to use the materialize modal in my laravel app, I've got a blade file called skeleton which I put all my "scripts" in and stylesheets etc. That yeilds the sections which I define in my single blade files. That works great, however I've had loads of issues with materialize lately.
When I try to use the modal, I use this code from the docs:
$(document).ready(function() {
$('.modal').modal();
});
That's at the bottom of my skeleton file and shows at the bottom of every file. I've tried putting it in my file itself and it didn't work.
My HTML looks like this:
#if($auth >= 5) <a href="#modal1" class="btn waves-effect waves-light green right modal-trigger"
href="#modal1"> Create</a>
#endif
at the bottom of the blade file:
<div id="modal1" class="modal">
<div class="modal-content">
<h4>Modal Header</h4>
<p>A bunch of text</p>
</div>
<div class="modal-footer">
Agree
</div>
My modal appears on screen, but it's automatically "shown" and when I click the open button it doesn't do anything. I'm just using the demo modal, I'll customize it when I can get it to work, thanks.
Here you go with a solution
For opening a modal please use the below code
$('.modal').modal('show');
For closing a modal please use the below code
$('.modal').modal('hide');
It's opening automatically because of
$(document).ready(function() {
$('.modal').modal();
});
Whenever the doument is ready then it's opens the modal.
On click
#if($auth >= 5) Create
#endif
Open the modal using $('.modal').modal('show');
Ok, first up, why two href's on the modal trigger?
#if($auth >= 5) <a href="#modal1" class="btn waves-effect waves-light green right modal-trigger"
href="#modal1"> Create</a>
#endif
Take one off, and let's take it from there.
The answer above incorrectly states that the init below opens the modal:
$(document).ready(function() {
$('.modal').modal();
});
This is just the initialisation, it plugs into the JS to allow it to work.
<!-- this is the initialisation -->
$('.modal').modal();
<!-- this is instruction to open -->
$('.modal').modal('open');
Check the pen here for the two commands, comment each out to see what happens.
Modals are closed by default, and are triggered by clicking the .modal-trigger or using the open command above..
I was being stupid, I had bootstrap js linked for some reason and they were conflicting. Sorry to waste anyone's time.

How to differentiate id or class without changing properties

I'm making a webpage that's using bootstrap-modal.js from Twitter bootstrap
bootstrap-modal.js allows you to create "modals." You basically click a button and a little javascript window slides down where you can display different content etc. Here's a demo http://jsfiddle.net/mjmitche/xt4aQ/44/
I'm going to have several buttons/modals on my webpage, so I have to set it up so each button triggers a different modal. I assume that the best way to do this is to give them different classes or ids
Problem, if I change the ids given by bootstrap-modal.js, it changes the properties of the modals...For example, it may remove or add a black screen backdrop etc. The fiddle linked to above shows how the code below works.
Question: Do you know how I could differentiate the modals so that each button triggers a different modal but allow them all to have the same properties?
<div id="modal-from-dom" class="modal hide fade">
<div class="modal-header">
×
<h3>Modal Heading</h3>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
Primary
Secondary
</div>
</div>
Button
<button data-controls-modal="modal-from-dom" data-backdrop="true" data-keyboard="true" class="btn important">Launch left Modal</button>
You said you can't use id's so why not classes? try adding a different class to each modal. Here is your updated fiddle: http://jsfiddle.net/xt4aQ/52/
And I tried changing the id to number "2" and it works just fine. Just copy all the code and change the id by appending an ascending number.