Reactjs - toggle switches not working when using local array - reactjs

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.

Related

Set checkbox checked state of checkbox group programmatically in Formik

I have a checkbox group (checkboxes with the same name), that I'd like to toggle them through an external button.
The parent component will map over the data and create multiple checkboxes given the data, like so:
(options.map(
option => (
<Field
name={field.name}
value={option.value}
component={CheckBoxButton}
/>
)
)}
And the CheckBoxButton is
const CheckBoxButton = ({
value,
field,
...props
}) => {
const [activeState, setActiveState] = useState(false)
return (
<div>
<Field
type="checkbox"
{...field}
{...props}
value={value}
checked={activeState}
/>
<Button
active={activeState}
onClick={() => {
setActiveState(!activeState)
}}
>
Toggle Checkbox
</Button>
</div>
)
}
Now on submission, it seems the checked={activeState} value passed to the field seemed to be ignored, nor that it triggers onChange when changed. I have tried to use setFieldValue() but since we have multiple checkboxes with the same name, it only captures the last value. To use it means I'd have to manually structure the value array and pop/add values, which seems like an overkill.
I also tried using useRef and setting ref.current.checked manually, but at no use.
Any insights on what I might be doing wrong, or how to properly set the value programmatically?
So, I managed to get a workaround that solves the problem by wrapping the button (now a div) and checkbox within the same Label, and overriding the state within the onChange event of the field. Each field would have a unique identifier id which the label binds to using htmlFor.
While a valid workaround, it would still be nice to have a programmatic way to do so.
const CheckBoxButton = ({value,field,...props}) => {
const [activeState, setActiveState] = useState(active)
const { handleChange } = useFormikContext()
const fieldId = `${field.name}-${value}`
return (
<label htmlFor={fieldId}>
<Field
id={fieldId}
type="checkbox"
{...field}
{...props}
value={value}
onChange={(event) => {
setActiveState(!activeState)
handleChange(event)
}}
className={style.checkbox}
/>
<span active={activeState} >
Toggle Checkbox
</span>
</label>
)
}

Toggle Switch unable to maintain the set value when onClicked

I want a toggle switch when onClicked would set thew current boolean value to its opposite. When the toggle button is clicked it sets to false but reverts back to true. I added a event.preventDefault to stop the refresh; however, though im getting the correct set value and stopped it from reverting back to default state when onClicked, the toggle no longer toggles left to right.
function CreateForm() {
const [isPrivate, setPrivate] = useState(true);
const handleStatus = (event) => {
// event.preventDefault();
setPrivate(!isPrivate)
console.log(isPrivate)
}
return (
<div className='createform__switch'>
<h5 className='createform__private'>Private</h5>
<label className="switch" htmlFor="checkbox" onClick={handleStatus}>
<input type="checkbox" id="checkbox" />
<div className="slider round"></div>
</label>
<h5 className='createform__public'>Public</h5>
</div>
)
}
how can I stop the value from reverting back to its default state but at the same time have a functioning animated toggle switch.
please, any help will be great
When you click on the checkbox you are calling the handleStatus method which changes the isPrivate value and then you are logging the value in the console. The thing is, that the isPrivate state is not been updated until the method execution is finished, so you are seeing the previous value in the console.
So the handleStatus method will look like this:
const [isPrivate, setPrivate] = useState(true);
const handleStatus = () => {
setPrivate(!isPrivate)
console.log(!isPrivate)
}
I also leave you some fixes of the code:
<div className='createform__switch'>
<h5 className='createform__private' style={{fontWeight: isPrivate ? "bolder" : "lighter"}}>Private</h5>
<input type="checkbox" id="checkbox" checked={isPrivate} onChange={handleStatus} />
<h5 className='createform__public' style={{fontWeight: isPrivate ? "lighter" : "bolder"}}>Public</h5>
</div>

Why do i have to click this radio button twice to set it active in react

Below is my code for handling the onClick for a radio button that uses images as its label
function foo(props) {
let id = props.id
id = id.replace(/[0-9]/g, '');
return (
<React.Fragment>
<input type="radio" name="foo" id={props.id} value={props.id} onClick={()=>{props.handle(id)}}/>
<label for={props.id}>
<Image src={props.src} style={foo} className="zoom" rounded />
</label>
</React.Fragment>
);
This is the code handling the state change for it
const [foo,setFooState] = useState("foo")
function updateState(e){
setFooState(e)
}
I am currently having an issue where I have to click the image twice in order for the radio button to be set as active
So i have found the issue which is i am passing the state change 2 parent up and that is causing some unintended issue.

How to disable tab button for specific inputs in 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>
);
}

ReactiveSearch only autocomplete

I want to use ReactiveSearch library only for autocomplete with submit.
const Search = () => (
<div className="search-field">
<ReactiveBase
app="good-books-ds"
credentials="nY6NNTZZ6:27b76b9f-18ea-456c-bc5e-3a5263ebc63d"
>
<div className="row">
<div className="col">
<DataSearch
dataField={['original_title', 'original_title.search']}
categoryField="authors.raw"
componentId="BookSensor"
/>
</div>
</div>
</ReactiveBase>
</div>
)
export default Search
I tried making the input as above with <DataSearch ... /> and it works, but it doesn't have submit option. I tried to wrap it with form, but after enter or select value it doesn't fire.
Any suggestions?
https://opensource.appbase.io/reactive-manual/search-components/datasearch.html
you need to read the doc carefully there is onValueChange handler so when you type in something you can set the state first set the initial state state = {searchText: ""} at the top after that in Data search prop you can do the following
<DataSearch onValueChange = {(e) => this.setState({searchText: value})} />
now make you own button and submit the value in the state for example this.state.searchText
ReactiveSearch now supports an onValueSelected prop which is perfect for usecases where you are only interested in utilizing the selected value (either selecting a suggestion or hitting Enter key). Docs and example usage:
<DataSearch
...
onValueSelected={(value) => console.log('The selected value is', value)}
/>

Resources