How to disable tab button for specific inputs in ReactJS? - reactjs

I have inputs on a few pages which I animate through. You have to click the button to get the next page and the next round of inputs, however when you get to the end of each page, you can hit the tab button and it focuses on the next input field which throws off the animation flow and display. Can I disable the tab button?

If all you want to do is prevent the field from receiving focus from a tab, you can set the tabIndex attribute to -1.
<form>
<input type="text" />
<input type="text" />
<button>button</button>
<input type="text" tabIndex="-1" />
</form>

If your goal is to disable "tabbing out" of an input field, you can listen to the keyDown event, and if the keyCode is 9 (value for Tab), then preventDefault on the event:
function MyComponent() {
return <input onKeyDown={(e) => { if (e.keyCode === 9) e.preventDefault() }} />
}
Rest of your code stays the same; i.e. however you handle input change:
function MyComponent() {
const [value, setValue] = React.useState('');
return (
<input
value={value}
onChange={(e) => setValue(e.target.value)}
onKeyDown={(e) => {
if (e.keyCode === 9) e.preventDefault();
}}
/>
);
}
From an accessibility and user experience perspective, I'd suggest not disabling Tab functionality. Some of your users might not have a mouse/touch input device or capability, or might want or prefer to use the keyboard exclusively for navigation. Tab is the natural way to advance among inputs, links, and buttons on web pages and it's best if you can preserve the functionality. Is there a way to deliver your animation experience while preserving Tab navigation?

Here's a sandbox to show you how to do this using React refs. Essentially, you can use the ref to store the DOM element you want to modify, making it really reusuable. In this case we just want to set that input's tabIndex to -1
https://codesandbox.io/s/vigilant-fermat-vihnc
function App() {
const skipInputRef = React.createRef();
useEffect(() => {
skipInputRef.current.tabIndex = -1;
}, []);
return (
<div className="App">
<input />
<input />
<input ref={skipInputRef} placeholder="skip" />
<button>Click</button>
</div>
);
}

Related

(Using React) Why is the submit button when onClick is performed using onChange events and resulting in empty string? (useState question)

Description:
The submit button calls a function called displayFields. This function then console logs the state of the input fields. The start of the input fields is listened to by onChange that sets the new state.
Before clicking the submit button the input fields when something is entered console logs the current state of the fields and then provides each string character in the console. To my understanding onChange should listen for changes but not console anything. When the button is clicked it should perform the function one time and console the current state of what is entered in fields. Instead when clicked the fields clear and then console an empty string.
I will provide my code and screen shots to help.
const GetQuote = (props) => {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [question, setQuestion] = useState("");
const dispFields = () => {
console.log(name + email + question);
};
/*
This is used in case prevent defualt needs used
function handleSubmit(e) {
e.preventDefault(); }
*/
return (
<React.Fragment>
<form
id="quoteForm"
//onSubmit={handleSubmit}
>
<h1 id="quoteTitle"> Quote Help Form </h1>
<p id="quotePar">
{" "}
Please provide your Name, Contact Email, and what products you would
like more information about in this form:{" "}
</p>
<label id="formName" className="Form">
Name:
<input
type="text"
name="name"
onChange={(event) => {
setName(event.target.value);
}}
/>
</label>
<label id="formEmail" className="Form">
Email:
<input
type="text"
name="email"
onChange={(event) => {
setEmail(event.target.value);
}}
/>
</label>
<br />
<label id="formQuestion" className="Form">
What products would you like to know more about:
<input
type="text"
name="help"
onChange={(event) => {
setQuestion(event.target.value);
}}
/>{" "}
</label>
<br />
<br />
<button
id="quoteSubmit"
type="submit"
//funtion is called however seems to constantly call the useState which is used in onchange
//when submit is done returns empty string
onClick={dispFields()}
>
Submit{" "}
</button>
</form>
</React.Fragment>
);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
onClick={dispFields()} is getting called on every render. If you pass it without calling it (onClick={dispFields} that should only log it to the console when the button is clicked.
You try to alter from
<
button id = "quoteSubmit"
type = "submit"
//funtion is called however seems to constantly call the useState which is used in onchange
//when submit is done returns empty string
onClick = {
dispFields()
} >
Submit < /button>
to
<
button id = "quoteSubmit"
type = "button"
//funtion is called however seems to constantly call the useState which is used in onchange
//when submit is done returns empty string
onClick = {()=>
dispFields()
} >
Submit < /button>
Changed "button" from "submit", arrow function involved
Both solutions provided above work. Changing to example = {example} from example = {example()}. Also calling it from a arrow function also works. The issue is a node issue. What happens when the use breakpoints is set on the function, the values are console logged however after they are console logged the form refreshes and then the state refreshes so the console logs are never logged because the browser processes the value of event and clears the event at the same time. So as long as the values can be passed to the backend, the front end can remain clearing the value being rendered.

How to Link A certain Keyboard Key to a function in React JS

I have made an App that is simple you can check it out here but the problem is now that when a user is logged in and creating a post there is a button that adds a post now I want "Enter" key to perform the same task the code to my button is
<Button variant="contained" color="secondary" onClick = {updateList}>Add item</Button>
now I want to bind the same updateList function to Enter key please guide me on how can I do that???
The button is from Material-ui
also currently as I click enter key it reloads the page I also want to stop that from happening
Also, can anyone tell me that is it possible to take multikey stroke input like ctrl + Z ?
If you want to bind function to some key you can do it by event listeners called onKeyDown or onKeyPress:
handleKeyPress = (event) => {
if(event.key === 'Enter'){
console.log('enter press here! ')
}
}
function App(){
return(
<div>
<input type="text" id="one" onKeyPress={this.handleKeyPress} />
</div>
);
}
Because you pager is reloading im guessing your using the HTML form tag. To prevent it the page from reloading your need to prevent the default event behavior after submitting.
<form onSubmit={(event) => {event.preventDefault() /* this stops reloading the page */ }} ></form>
To be able to submit on enter, you should add a button in side the form tag and add type "submit" to it.
<form onSubmit={(event) => {event.preventDefault() /* this stops reloading the page */ }} >
<button type={"submit"}/>
</form>
That should do it.

How to get the ref.current dom element when using react-select and react refs?

I have a group of react selects using the react-select package – https://react-select.com/home.
I have a component that wraps three react-selects – something basically like this:
import Select from "react-select"
function SelectGroup(){
const ref1 = useRef(null);
const ref2 = useRef(null);
const ref3 = useRef(null);
return (
<div>
<Select ref={ref1} />
<Select ref={ref2} />
<Select ref={ref3} />
</div>
)
}
I need to perform some checks to see what's in focus. The reason I am doing this is because the group of selects is a single component that needs to be able to allow the user to navigate in multiple ways through the keyboard. Spacebar, and enter keys should allow the user to shift the focus to the next select element. Arrow keys should allow the user to go to the next or previous select. So, focus needs to be managed somehow, and this means knowing what's currently in focus.
Normally, I would do that like this:
function isActiveElement(ref){
return ref?.current === document.activeElement
}
However, for ref.current react-select returns an object called StateManager – https://react-select.com/props#statemanager-props
So, ref.current === document.activeElement always returns false.
How, can I check to see which react-select is in focus? I was unable to find anything about this in the react-select docs. Maybe, I'm missing it? I have solved this problem others ways, but I was curious if there is a way to do it this "simpler way" I describe above, which may be the more common approach.
You can listen to the focus and the blur event to keep track of the currently focused Select:
export default function App() {
const [focus, setFocus] = useState(-1);
const onBlur = () => setFocus(-1);
return (
<div>
<div>Current focus: {focus}</div>
<Select
onFocus={() => setFocus(0)}
onBlur={onBlur}
options={colourOptions}
/>
<Select
onFocus={() => setFocus(1)}
onBlur={onBlur}
options={colourOptions}
/>
<Select
onFocus={() => setFocus(2)}
onBlur={onBlur}
options={colourOptions}
/>
</div>
);
};
Live Demo

Reactjs - toggle switches not working when using local array

I have an update for anyone that is reading this....
I think I've found the issue - when you set a toggle switch to checked it's also set to READONLY. So I can't toggle the toggle switch now.
I have a toggle component of type checkbox in React.
products is a locally set array for testing purposes as this.props.products is empty for now.
Through testing, I've noticed that if I use:
selected={(products.indexOf(p) > -1)} the toggles stop working. They display correctly but I'm not able to toggle them. They do not appear disabled or are set to disabled in HTML element.
products=['ProdA', 'ProdB', 'ProdC];
customerProducts.forEach(p => {
content(): string[] {
const toggles = [];
if(isEnabled){
toggles.push(
<ToggleComponent
value={p}
selected={(products.indexOf(p) > -1)}
onChange={this.props.onChange}
disabled={false}
/>
);
}
render() {
{this.content()}
}
//TOGGLE COMPONENT
render() {
const {id, title, disabled, name, value, selected} = this.props;
return (
<div>
<fieldset>
<div className="form-structure">
<label className={!this.props.disabled ? 'checkbox-switch-label' : 'checkbox-switch-label checkbox-switch-label-disabled'}>
<input id={id} type="checkbox" checked={selected} className="checkbox-switch" role="Switch" disabled={disabled} name={name} value={value} onChange={this.validate} />
<span/>{title}
</label>
</div>
</fieldset>
</div>
)}
I can see there is an invalid Event Listener in my dev Tools: dispatchDiscreteEvent
The toggles are appearing, are not visibly disabled, (there is no disabled attribute in the html element), but clicking them does not toggle them on/off.
Am I supposed to be setting 'disabled' against a state value instead?
I already have an onChange function elsewhere for getting the values.

How to force Enter key to trigger "submit" function without need to focus an input

I'm making an app in react-redux and I want a simple feature but that's starting to look tricky to implement.
:)
I want to be able to open my webapp (I land on my login screen) and just hit enter (the browser has already saved my user and password and they are filled in in the correct input fields) and have that "enter" keystroke tigger my login function without me needing to click anywhere first to focus something.
(On a non-root component)
I've already got my password input (the last one) bound to the enter key correctly.
So pressing enter when I have the password field focused works :
handleSubmit() {
const { authenticate } = this.props;
const { tusername, tpassword } = this.state;
const credentials = {
username: tusername,
password: tpassword,
};
authenticate(credentials);
}
_handleKeyPress = (e) => {
if (e.key === 'Enter') {
this.handleSubmit();
}
};
render() {
return (
<div onKeyPress={this._handleKeyPress} >
<Card id="signin">
<CardImg top width="100%" src={rubisLogo} alt="Rubis" />
<InputGroup>
<Input
placeholder="Nom d'utilisateur"
value={this.state.tusername}
onChange={this.updateUser}
/>
</InputGroup>
<InputGroup>
<Input
placeholder="Mot de passe"
type="password"
value={this.state.tpassword}
onChange={this.updatePassword}
onKeyPress={this._handleKeyPress}
/>
</InputGroup>
<div>
<Button
id="btn"
onClick={this.handleSubmit}
to="/home">Login
</Button>
</div>
<ModalPassword class="modal" buttonLabel="Mot de passe oublié ?" />
<ModalAccount class="modal" buttonLabel="Créer un compte" />
</Card>
</div>);
}
as you can see I've tried putting it on the div but that didn't work. also I don't want a solution based on that. I want the enter-key to be a gobal fallback on this view. the user can't loose this funtionality just because he clicked somewhere.
Set the focus to the div by default using tabIndex so that the javascript event will be triggered
render() {
return (
<div onKeyPress={this._handleKeyPress} tabIndex="1" >
<Card id="signin">
..)}
You have to wrap your components with a form tag instead of a div, handle the onSubmit event, and the property type of Login button you must set it to submit.
...
handleSubmit = (e) => {
e.preventDefault(); // prevent browser behavior
// Handle submit logic
...
};
render() {
return (
<form onSubmit={handleSubmit}>
...
<Button
id="btn"
type="submit"
to="/home">Login
</Button>
</form>
);
}

Resources