I have used react-modal for modal dialog,
and in my reactjs render(), i have the following modal
return(
<ReactModal
isOpen={this.state.showModal}
contentLabel="Minimal Modal Example">
<button style={styleClose} onClick={this.handleCloseModal}>
CloseModal</button>
{items}
</ReactModal>
)
But when this dialog open, the items behind are overlapping, how can I have only dialog being visible and not the background elements?
The elements that are overlapping are the components that have radiobuttons. Normal text are not overlapping. How can i make these buttons not to overlap?
I tried setting the zIndex and apply styling but that doesnt work.
Also how can i have close when i also click esc on keyboard ?
The first part of your question needs more info for clarification, I can answer the second part:
Add this to your modal element:
shouldCloseOnEsc={true}
If you haven't, remember to also add onRequestClose={<your component method that hides the modal}
Check this link for more usage: http://reactcommunity.org/react-modal/#usage
Related
I am using Material-UI in my React app, and I have a Dialog that appears over several form elements after I click a button.
I also have that dialog set to allow it to be dragged using react-draggable.
When the dialog is showing, none of the form elements behind it are ale to be accessed. I realize it intuitively makes sense to block interaction with the elements behind the dialog.
However, I am trying to figure out how to have the dialog showing, and yet still being able to edit the form elements behind it.
Code example here:
Does anyone know if it's possible to show a MaterialUI Dialog and still be able to interact with form elements behind the dialog (ie, when the dialog is dragged away)?
The dialog was meant to block all other interaction so the user can focus on its contents. Anyway, I found one solution, probably not the better but is working here, the code is this:
<Dialog
hideBackdrop // Disable the backdrop color/image
disableEnforceFocus // Let the user focus on elements outside the dialog
style={{ position: 'initial' }} // This was the key point, reset the position of the dialog, so the user can interact with other elements
disableBackdropClick // Remove the backdrop click (just to be sure)
...
>
...
</Dialog>
Here a working example
It is possible, and without too much trouble! When the Dialog is opened, its root container is a div with a class of MuiDialog-root, spawned directly in your <body>. Instead of putting the react-draggable component around the dialog's PaperComponent, we put it around the entire dialog:
<Draggable
handle={'[class*="MuiDialog-root"]'}
cancel={'[class*="MuiDialogContent-root"]'}>
<Dialog
// Styling goes here
>
... // Dialog contents
</Dialog>
</Draggable>
Then, it's necessary to style the Dialog a little. We need to make sure to disable the backdrop, then bring the container size down so that when we click behind it, we are actually selecting other components:
<Dialog
open={open}
onClose={handleClose}
disableEnforceFocus // Allows other things to take focus
hideBackdrop // Hides the shaded backdrop
disableBackdropClick // Prevents backdrop clicks
PaperComponent={PaperComponent}
style={{
top: '30%', // Position however you like
left: '30%',
height: 'fit-content', // Ensures that the dialog is
width: 'fit-content', // exactly the same size as its contents
}}
>
...
</Dialog>
Note the PaperComponent property. As per the material-ui docs on draggable dialogs, this refers to the surface that holds the dialog contents. However, instead of wrapping the paper in a <Draggable>, we need to create this component for styling. If we don't, the PaperComponent will have large, obnoxious margins and won't fit properly in its parent.
function PaperComponent(props: PaperProps) {
// PaperProps is an import from '#material-ui/core'
return (
<Paper {...props} style={{ margin: 0, maxHeight: '100%' }} />
);
}
Be sure to place this function outside of the rendering component. Otherwise, every time the state changes, your dialog contents will be remounted. This was bad for me because I was using an Autocomplete field in the dialog, and every time I selected an option and did something with the onChange(), the text input would disappear. Changing the function scope fixed this problem.
disabling enforce focus can also disturb the origin and position
Use disableAutoFocus
<Dialog
hideBackdrop={true}
disableBackdropClick
disableAutoFocus
...
>
....
</Dialog>
How to hide bootstrap modal from javascript without using jquery.
None of the following work :
document.getElementById('id_1').modal('toggle');
document.getElementById('#id_1').modal('toggle');
document.getElementById('id_1').modal('hide');
If I add a class hide it works. The modal hides, But the main screen stays grey. Focus never shifts to the main screen until I click on the screen.
Thanks
You can use v-if attribute on modal to toggle it. <b-modal v-if="isVisible">
I tried many solution but the one I created and worked for me is:
add a close button (the default one given by Bootstrap modal template) and if you want you can add a d-none class to it if you want to hide it.
Then in your Javascript code :
var close = document.getElementById("closeButton");
close.click();
I have a little question about some techniques that are used to render/not render modals.
At the moment there are 2 main ways to do so.
For the first example, we use a visible prop onto the modal and based on that, we will apply a style that will hide the modal. This will be handled by state and then toggled with a button for example :
<Modal
title="Foo"
visible={this.state.visible}
>
Foo
</Modal>
The second way of doing also use state, but uses a condition to render the modal or not :
{this.state.visible && (
<Modal title="Foo">
Foo
</Modal>
)}
The handy thing with this is that the modal will not be rendered until it should.
So what is the best way of doing? I suppose the 2 are right but is there one that is better than the other?
Personally second one is better, because by checking the state at Parent Component, you separate Parent Component logic and Child Component logic, since Modal component only responsible for showing the modal, but the logic whether open or close modal belongs to Parent Component logic. But both solutions will work :)
Just research the question in UI libs docs: antd, material-ui, semantic-ui.
And you will find the answer => prop (with names open, show, visible etc.) is the best way to control visibility (inner state of component).
For example you can see antd modal that use this package
(react-component/dialog):
https://github.com/react-component/dialog/blob/master/src/Dialog.tsx
You can return null or use css (display: none; for sample) for invisible modal
Popup-like components in Material-UI render on an invisible top overlay that is programmatically appended directly to body. For example, when a SelectField or DropDownMenu is opened:
<body>
<div id="app-container>
<div ...>
<!-- This is where the SelectField is rendered. -->
</div>
</div>
<div ...>
<!-- This div is: -->
<!-- (1) where the visible dropdown is rendered when open -->
<!-- (2) a full-screen overlay -->
<!-- (3) removed when the dropdown is closed -->
</div>
</body>
This mechanism is in place so that (1) the user can "click away" to close the open dropdown, (2) the user does not accidentally click on another control when attempting to close the open dropdown.
However, I need to allow clickaways to actually hit the underlying element, without being blocked by the overlay. This can be accomplished in the Popover component by using the useLayerForClickAway prop:
<Popover useLayerForClickAway={false} ... >
...
</Popover>
Unfortunately, no such option exists for SelectField or DropDownMenu (or seems to exist, it's not documented), and I need one of these instead of a Popover.
Moreover, I don't seem to find any option that allows to reliably identify the overlay element created by the dropdown, beside getting the last element in body immediately after the dropdown opened (which is hackish at best). Material-UI also doesn't seem to offer a way to manually override the inline styles of this overlay element.
So, what's the "appropriate" way to disable the invisible overlay, and allow clicks when the dropdown is open?
My store's collection pages have the quick-view feature where hovering over products images allow you to click 'Quick View' to open a modal dialog window with summary info about the products. This is done with the leanModal plugin.
See: http://froy.com/collections/beds-mattresses for example. Store is powered by Shopify.
The problem is, when the page initially loads, all the elements within the modal are loaded despite being hidden. This unnecessarily slows down the site. I'd like to load the contents within the modal only after the user clicks on 'Quick View.'
<div class="quick_shop"> <!--This is the modal trigger-->
<div class="quickview-text">Quick View</div>
</div>
<div class="modal">
<!--All contents of the modal dialog window go in this div-->
</div>
Script:
$('.quick_shop').leanModal(); //Calls the function on the modal trigger
(function($){$.fn.extend({leanModal:function(_1)...});})(jQuery);
//The above line of code is for leanModal. I didn't paste entire thing cause it's long
Any help would be much appreciated! I'm new and learning so this is all very exciting.
The purpose of the modal div is to have a precise view on one specific element.
In your case (on the webpage you provided), the modal is loaded for each element, which breaks the sense of what you're trying to achieve.
I've never used the leanModal plugin but I guess you could try doing the following:
When the "Quick view" is pressed, find the closest element with jQuery .closest() method by searching the element with class .quick_shop, THEN leanModal that single element and display it:
$(".quickview-text").on("click", function(e){ $(this).closest(".quick_shop").leanModal(); //Then display it with .show() if it's hidden by default });
Once the modal is closed you can delete the element instead of hiding it with the jQuery's remove() method.