How to avoid the React Datepicker to close when clicking outside - javascript

I'm using the react-datepicker component on my application (https://www.npmjs.com/package/react-datepicker).
I want to close the datepicker calendar only when I click on a certain element that I created on the surrounding of the component, but the default behavior of the datepicker is to close when I click in any place outside him.
How can I do this? I tried this:
<ReactDatePicker selected={startDate}
startOpen
shouldCloseOnSelect={false}
withPortal
onClickOutside={(e: any)=> { e.preventDefault(); e.stopPropagation(); }} />
But it didn't worked.

Related

MUI: button within a MenuItem: When I click the button without clicking the MenuItem?

I am using MUI's Menu / MenuItem to build a menu of missions / tasks like this screenshot:
The MenuItem is clickable:
// ... other code
<MenuItem
value={mission.issueIdentifierId}
sx={{px: 0.5}}
onClick={() => handleMenuItemClick(mission.issueIdentifierId)}
>
<UploadMissionCard mission={mission} />
</MenuItem>
// ... other code
and when it is clicked, a modal window will pop up to show the detail info.
Now, within the MenuItem, there is the UploadMissionCard component, and in some cases, the UploadMissionCard would contain a MUI Button called Abort. On clicking the button, a different warning modal window will pop up.
However, when I click the button, the clicking action propagates to the menuItem as well and the menuItem is also clicked. So both modal window are opened.
In MUI, how can I put a Button inside a MenuItem and stop the clicking action on the button from passing on to the parent MenuItem?
Call stopPropagation method on button click event
<button onClick={(event) => {
event.stopPropagation();
}}></button>

Material UI's ClickAwayListener firing right away, which causes state to toggle twice

I have been doing research on this for days and finally have decided to ask this on here. I am using react and material-ui's ClickAwayListener component. The idea is that I have a button, which toggles the this.state.showGridPopup to the opposite of whatever it is currently is. So if the user was to click it once, the grid popup should show, click it again, the popup should disappear. There is an handleShowGrid handler attached to the button that does this:
handleShowGrid = (event) => {
const { widgetButtonEl } = this.state;
const element = widgetButtonEl === null ? event.currentTarget : null;
console.log('In handleShowGrid!!!!!');
this.setState({
showWidget: !this.state.showWidget,
widgetButtonEl: element
});
}
All this works well. And toggles the popup to show when we click on the button attached to the handler.
<ButtonBase onClick={this.handleShowGrid}>Open Swap</ButtonBase>
The issue is when I add Material-UI's ClickAwayListener. The reason for adding this is to close the grid when a user clicks outside the grid. Here is the ClickAwayListener below:
<ClickAwayListener onClickAway={this.handleCloseWidget}>
<SurveyGrid />
</ClickAwayListener>
And the handleCloseWidget handler:
handleCloseGrid = (e) => {
console.log('In handleCloseWidget!!!!!');
this.setState({
showWidget: !this.state.showWidget,
widgetButtonEl: null
});
}
So now clicking outside grid is fine and closes the Grid. However, now, clicking on the button that should toggle the Grid being show (this.state.showWidget), causes the handleCloseGrid to fire. And then afterwards the handleShowGrid would fire. Is there anyway to not have the handleCloseGrid handler to fire? It seems like an issue with propagation and event bubbling. Have tried different things like e.stopPropagation() but to no avail.

Vue & Quasar - Sharing a custom dialog component

I've looked at Reuse Quasar Dialog plugin with custom component on another component that does not have any answers and I have close to the same question but I have structured code a bit different. On my parent form I have
<q-dialog prevent-close v-model="showProfileForm" class="profileDialog">
<profile-dialog></profile-dialog>
</q-dialog>
and my profile-dialog is a form that is a simple template
<template>
<q-stepper
It seems that if I wrap the component on the parent page the dialog will open BUT I cannot pass in
prevent-close
or add a
#hide
I need to know when the dialog form is closed to save changes or prevent closing unless a button is clicked. Even adding the prevent-close in the parent does not work
<q-dialog prevent-close v-model="showProfileForm" class="profileDialog">
<profile-dialog></profile-dialog>
</q-dialog>
If I create the form inside a q-dialog, so it becomes a dialog inside a dialog and set the v-modal to true when it closes the parent form still has the slight gray overlay until the page is clicked and the form will not open a second time
You can use the emit event in profile dialog for pass event so that you know that form is submitted or not and use persistent so that User cannot dismiss Dialog if clicking outside of it or hitting ESC key; Also, an app route change won't dismiss it.
<q-btn v-if="step == 4" #click="FinishClick" color="primary" label="Finish"/>
methods: {
FinishClick() {
alert("Finish Click From Profile Dialog");
this.$emit("profile_dialog_emmit",{'MSG':'TestData'})
}
}
<profile-dialog #profile_dialog_emmit="my_fun($event)"></profile-dialog>
In Parent Component.
methods:{
my_fun(data){
console.log("Assad");
alert("From Index Check Console for Data");
console.log(data)
this.showProfileForm=false;
}
}
Demo - https://codesandbox.io/s/clever-kilby-qf1gz
Go to the final step and click on finish will trigger the event and you can see an alert from the parent component and check the console for data displayed from the parent component.

Solved: React-day-picker Daypicker Input loses focus when using custom input component

The working sandbox is https://codesandbox.io/s/react-day-picker-base-h9fv6
I have been trying to implement a simple day picker input, where you can both enter the date in the input field and select in the picker.
The problem is that when I use a custom input,
<DayPickerInput component ={CustomInput}.../>, the input loses focus when the picker is used. This does not happen without a custom input. In the docs it says
"If you want to keep the focus when the user picks a day, the component class must have a focus method."
However I am not sure how I should implement this.
If you need a custom component with a focus method, I think you need to use a class component, and refs:
class Input extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
focus() {
this.inputRef.current.focus();
}
render() {
return <input {...this.props} ref={this.inputRef}/>
}
}
I use the MaskedInput component from "react-text-mask" library, and custom overlay component for 'Date Range picker with two inputs' from 'react-day-picker'.
Custom overlay and input:
const renderMaskedInput = (_props, _ref) => {
return (
<MaskedInput
mask={getLocaleMask}
showMask
ref={_ref}
type="text"
render={(ref, inputProps) => <input ref={ref} {...inputProps} />}
{..._props}
/>
);};
<DayPickerInput
component={_props => renderMaskedInput(_props, startInputRef)}
overlayComponent={_props => (
<Popper
open={Boolean(startAnchorEl)}
anchorEl={startAnchorEl}
style={{ zIndex: 10000 }}
>
<div {..._props} className={customOverlayWrapper}>
<div className={customOverlay}>{_props.children}</div>
</div>
</Popper>
)}
My problem was in losing focus from the picker input when opening or clicking on the custom overlay, and the 'keepFocus' prop is did not work with custom input. So it causes problems with closing overlay after clicking on backdrop, because the overlay is closing only by 'onBlur' of input.
Just hard-setting focus on the input by onClick or something else did not work. My solution is setting focus in useEffect after changing input ref when the custom overlay is opening, but it did not enough because the focus is losing after clicking on the overlay, so we just setting focus to input after 3 handlers of DayPicker: onFocus, onMonthChange, onCaptionChange (see codesandbox example).
And using Popper as a custom overlay for DayPickerInput solves a problem with rendering overlay in a free area at the screen (auto-positioning of overlay). Also, Popper works with Portal and it solves many problems with rendering overlay.
Full code: https://codesandbox.io/s/optimistic-glitter-c77gb
Short version:
const focusStartInput = () => {
startInputRef.current.inputElement.focus();
}
useEffect(() => {
// used because 'keepFocus' prop from the library does not work with the custom
// overlay or with the react-text-mask input
if (startAnchorEl) {
// if the start picker overlay is open
focusStartInput(); // input loses focus after overlay opening,
// so just reset focus
}
if (endAnchorEl) {
// if the end picker overlay is open
focusEndInput(); // input loses focus after overlay opening, so just reset focus
}
}, [startAnchorEl, endAnchorEl]);
<DayPickerInput
dayPickerProps={{
onMonthChange: focusStartInput,
onFocus: focusStartInput,
onCaptionClick: focusStartInput,
}}
There is a problem with a solution from the main question. His input loses focus if we clicking not on the day in date picker (on the caption, month navigation, or somewhere else). My code helps to solve it.

Input lose focus on click in paper-dialog Polymer

I am using Paper-dialog and paper-dialog-scrollable webcomponents in Polymer projects. I have some set of input fields (Forms) on paper-dialog (pop-up). By default when opening popup(Dialog) I am focusing input field.
But issue is when i click, scroll anywhere inside the dialog, Input lose it focus. How should i keep focus inside paper-dialog even if i click/scroll
i tried below code but no luck. form code wrote inside another element called my-form-element
<paper-dialog-scrollable id="myDialog">
<my-form-element></my-form-element>
</paper-dialog-scrollable>
Polymer.RenderStatus.afterNextRender( this, function() {
const dialogContent = this.$.myDialog.$.scrollable;
dialogContent.addEventListener('click', (e) => {
e.preventDefault();
});
});

Categories