I have built a navigation hamburger using a checkbox toggle to reveal/hide the menu so the menu works if the user is on a non-JS browser.
However, this means that keyboard users have to know to press space to toggle the menu, when the expected functionality for buttons would be the return key.
Is there an efficient way to toggle the checkbox with the return key if the user is focussed on it or shall I just leave it with the spacebar?
I think that the simplest way would be to write script to get all bubbled keypress events and toggle inputs.
<input type="checkbox" class="js-toggle-enter" />
document.addEventListener('keypress', (e) => {
if( e.key === "Enter" && e.target.classList.contains('js-toggle-enter')){
e.target.checked = !e.target.checked;
}
})
Related
I want to display the password validator popup as users type their passwords. I tried to do with onFocus or onClick, however, it seems like it triggers just once. Is there any attribute to determine if a user clicks certain input and stays in that field?
I'd tried to do with hooks, however, I am stuck on how to reset the value when use is off the password input to take off the popup. Like the picture below, the popup will only stay open when the user is typing in that field.
You can use onChangeText function to capture the events while user is typing in textbox. You can use onBlur event of textbox which is fired when user moves out of the textbox
<TextInput
onChangeText={(text) => {
// Display the popup here
}}
onBlur={() => {
// Remove the popup here
}}
/>
I have a material UI autocomplete component in a ReactJS application which I desire to have the following behavior:
The user can type input into the autocomplete, and when the user presses enter without scrolling through the suggested choices, event A is fired with the input typed in the autocomplete as a parameter.
The user can scroll through the suggested choices (with arrow keys), and when the user presses enter, event B is fired with the currently selected autocomplete choice in the parameter
The user can scroll through the suggested choices (with arrow keys/mouse scroller), and when the user clicks one of the suggestions, event B is fired with the clicked autocomplete choice in the parameter
I was able to make these behaviors individually. I handled the first behavior with an onKeyDown waiting for an enter key, and the second + third behavior with an onChange as suggested here:
stackoverflow.com/questions/58666189/getting-the-value-in-the-react-material-ui-autocomplete.
The problem appears when I put both events together. When I attempt to scroll through the choices with arrow keys and press enter (behavior 2), both the onKeyDown and onChange events get fired. This fires BOTH event A with what the user typed and event B with what the user selected, when I only want to fire event B with what the user selected. Is there a way to detect if the user has begun scrolling through the autocomplete suggestions with arrow keys (so that I can wrap event A in an if condition), or an alternative way to look at this problem to resolve it?
The Autocomplete component:
<Autocomplete options={someArrayOfStrings}
onChange={this.submitComment} // event B
onKeyDown={this.submitCommentEnter} // event A
value={this.state.userInput} // what the user has typed
autoComplete
freeSolo
renderInput={(params) => <TextField {...params}
fullWidth
label="Search"
variant="outlined"/>}/>
Event A (submitCommentEnter):
submitCommentEnter(e) {
if (e.key == 'Enter') { // possibly add check if user is scrolling through autocomplete with arrow keys here?
/* content of event A here; uses this.state.userInput */
}
}
Event B (submitComment):
submitComment(event, value) {
if (value !== null) {
/* content of event B here; uses value */
}
}
You don't need to handle the keyDown event, You just need to use the reason of on-change event as per document onChange provide three params
onChange={(event, value, reason) => {
console.log("onChange", reason, value, event.currentTarget);
}}
The reason can be of 5 types "create-option", "select-option", "remove-option", "blur" or "clear". when you press enter in text field reason will be create-option and when you select an option from the drop-down the reason will be select-options, below is the complete code to verify the fact.
import React from "react";
import TextField from "#material-ui/core/TextField";
import Autocomplete from "#material-ui/lab/Autocomplete";
const someArrayOfStrings = ["test", "test2", "test3"];
export default function CheckboxesTags() {
const [selectedValues, setSelectedValues] = React.useState();
return (
<React.Fragment>
<Autocomplete
options={someArrayOfStrings}
onChange={(event, value, reason) => {
console.log("onChange", reason, value, event.currentTarget);
// setSelectedValues(value);
}}
value={selectedValues} // what the user has typed
autoComplete
freeSolo
renderInput={params => (
<TextField {...params} fullWidth label="Search" variant="outlined" />
)}
/>
</React.Fragment>
);
}
I have also created this code-sandbox project, where you can check the console for
When the button was clicked it stay focused so if the enter or space key is pressed it counts as click but I need it to only work with the mouse click
If you only want a button to work on mouse click then you can try using any of the mouse events instead of using the onClick event.
<button onMouseDown={(event) => console.log(event)}> Button </button>
In your case, you should use the onMouseDown event.
It will only get fired when the mouse is clicked and not on any key press.
You can add an if check to your button function to see what key was pressed and do nothing unless the mouse was used to click it.
const onButtonClick = (event) =>{
//32 is for space-bar
//13 is for enter
if(event.keyCode === 32){
//leave blank so when space is used to press the button it wont do anything
}else if(event.keyCode === 13){
//leave blank so when enter is used to press the button it wont do anything
}else{
//add what you want to do when button is clicked here
//this runs when the button is not pressed using enter or space
}
}
On your react button component:
<button onClick={ onButtonClick }>My Button</button>
In React (not React Native), how can I slide the page-content up to make room for the iOS keyboard when a textarea element gains focus?
Below please find my attempt. This now works fine. However, I am curious if this is considered good practice, or if there is an existing solution?
// When the textarea element gains focus,
// scroll the content up (to make room for the iOS keyboard)
scrollContent = () => {
console.log("Gained focus");
this.scrollViewRef.current.style.marginTop = '-250px';
}
// When the textarea element loses focus,
// scroll the content back down (since the iOS keyboard is gone now)
unScrollContent = () => {
console.log("Lost focus");
this.scrollViewRef.current.style.marginTop = '0px';
// The textarea's onBlur is causing the button's onClick not to fire
// so need to manually call the button's onClick
if(e.relatedTarget === this.buttonRef.current) {
this.buttonRef.current.click();
}
}
render() {
return (
<div
ref={this.scrollViewRef}
>
<textarea
onFocus={this.scrollContent}
onBlur={this.unScrollContent}
/>
<div
ref={this.buttonRef}
onClick={this.handleSubmitForm}
tabIndex="1"
>
Save
</div>
</div>
)
}
In particular, if the user tries to click on the form's submit button while the textarea element has the focus, it will only trigger the textarea's onBlur (and scroll the page-content up again), but it won't call the submit button's onClick. Hence the need to check what element was clicked on in the if statement, and if it was the button, manually trigger the click.
Is there a better way?
I have component where it displays questions . Each question is react component. On press of Enter it should navigate to next question. I have wired onKeyPress to Div element , but event gets captured sometimes , and sometimes it doesn't.
<div className="-" onKeyPress={(e) => this.navigateToNext(e)}>
<div className="preview-head">
//Other stuff here
</div>{/* preview-container*/}
</div>
navigateToNext(e) {
if (option.get('selected') === true && e.charCode === 13) {
this.goToNextQuestion();
}
}
Can anyone tell me any other way to handle this problem.
I would wire up an event listener in componentWillMount for the keyup event and check it's the enter key. Just remember to remove the event listener in componentWillUnmount.
I would guess the issue is around the div having focus or not. If it is not focused the key press event doesn't fire on that element and thus nothing happens
As said by #spirift, your div has not the focus. Try this :
Add ref={(c) => { this.ref = c }} to your div and focus in a lifecycle method :
componentDidMount() {
this.ref.focus();
}