checkboxes bootstrap react radio buttons not working - forms

I'm building a form where it has two checkboxes the user is allowed to choose only one not both of them
I have used the react-bootstrap form
here is my code:
const [checked, setChecked] = useState("");
const [sechecked, setSechecked] = useState("");
return
<Form style={{ display: "flex" }}>
<Form.Check
value={checked}
onChange={(e) => setChecked(e.target.checked)}
type="radio"
aria-label="radio 1"
/>
Turkiye'den gonder
<Form.Check
value={sechecked}
onChange={(e) => {
setSechecked(e.target.sechecked);
console.log(checked);
}}
type="radio"
aria-label="radio 2"
/>
Turkiye'ye getir
</Form>
so, what I want is to only choose one checkbox and after that, the user can't choose the other one

Kindly add a name property to indicate the two options point to the same thing. In that case, only one can be selected
const [checked, setChecked] = useState("");
const [sechecked, setSechecked] = useState("");
return
<Form style={{ display: "flex" }}>
<Form.Check
value={checked}
name="useroption"
onChange={(e) => setChecked(e.target.checked)}
type="radio"
aria-label="radio 1"
/>
Turkiye'den gonder
<Form.Check
value={sechecked}
name="useroption"
onChange={(e) => {
setSechecked(e.target.sechecked);
console.log(checked);
}}
type="radio"
aria-label="radio 2"
/>
Turkiye'ye getir
</Form>

Related

How to wait for a checkbox to be selected in Testing Library

I have a simple component that looks like this :
function Checkboxes(props) {
return (
<div>
<input className="item-box-checkbox-1" type="checkbox" checked={getIsChecked(1, props)} />
<input className="item-box-checkbox-2" type="checkbox" checked={getIsChecked(2, props)} />
<input className="item-box-checkbox-3" type="checkbox" checked={getIsChecked(3, props)} />
<input className="item-box-checkbox-4" type="checkbox" checked={getIsChecked(4, props)} />
...
</div>
)
}
I would like to use Testing Library to "listen" on a checkbox click. As soon as the checkbox is checked I would like to proceed with my test.
Behind the scenes after checking on the checkbox some things are happening. After these things have happened then the checkbox should display as checked.
I have tried the following :
fireEvent.click(checkboxes[1]);
await screen.findAllByRole('checkbox', {checked: true})
But this does not seem to work.
There also seems to be a screen.getByRole("checkbox")).toBeChecked() . But I need to wait for the checkbox to be checked. screen.get* functions as I understand to not provide for this.
it is hard to tell what some things are happening but assuming we have sth like this:
import React from "react";
function Checkboxes(props) {
const [checked1, setCheck1] = React.useState(false);
const [checked2, setCheck2] = React.useState(false);
const [checked3, setCheck3] = React.useState(false);
const [checked4, setCheck4] = React.useState(false);
return (
<div>
<input className="item-box-checkbox-1" type="checkbox" onChange={setCheck1} checked={checked1} />
<input className="item-box-checkbox-2" type="checkbox" onChange={setCheck2} checked={checked2} />
<input className="item-box-checkbox-3" type="checkbox" onChange={setCheck3} checked={checked3} />
<input className="item-box-checkbox-4" type="checkbox" onChange={setCheck4} checked={checked4} />
</div>
)
}
export default Checkboxes;
Then your code work for me. You may also try to waitFor:
import { fireEvent, render, screen, waitFor } from '#testing-library/react';
import Checkboxes from "../Checkboxes";
it('should work', async () => {
render(<Checkboxes />);
const checkboxes = screen.getAllByRole('checkbox');
expect(checkboxes[1]).not.toBeChecked();
fireEvent.click(checkboxes[1]);
const checked = await screen.findAllByRole('checkbox', {checked: true})
expect(checked).toHaveLength(1);
await waitFor(() => expect(checkboxes[1]).toBeChecked())
})

MERN, how to update multiple input field from frontend in MongoDB

I am trying to update multiple fields and also want to keep data as it was previously which I don't want to edit.
I can update a single field but by manual typing not dynamically and also have no idea how to grab all other fields with which one I won't change.
I attached my code by which I can set only one field update,
const EventEdit = () => {
const [events, setEvents] = useState([]);
useEffect(() => {
const uri = `http://localhost:5000/eventss/${keyId}`;
fetch(uri)
.then((res) => res.json())
.then((data) => setEvents(data));
}, [user, keyId]);
return (
<form onSubmit={submitRegister} method="">
<div className="event_details">
<Form.Group className="mb-3" controlId="eventName">
<Form.Label>Event Name</Form.Label>
<Form.Control
type="text"
name="name"
placeholder=""
defaultValue={events?.name}
onChange={handleOnChange}
required
/>
</Form.Group>
<div className="event_type_check">
<label>
<input
type="checkbox"
defaultChecked={evTypeFilm}
onChange={() => setEvTypeFilm(!evTypeFilm)}
/>
Film Festival
</label>
<label>
<input
type="checkbox"
defaultChecked={evTypeScreen}
onChange={() => setEvTypeScreen(!evTypeScreen)}
/>
Screenwriting Contest
</label>
<label>
<input
type="checkbox"
defaultChecked={evTypeMusic}
onChange={() => setEvTypeMusic(!evTypeMusic)}
/>
Music Contest
</label>
<label>
<input
type="checkbox"
defaultChecked={evTypePhoto}
onChange={() => setEvTypePhoto(!evTypePhoto)}
/>
Photography Contest
</label>
<label>
<input
type="checkbox"
defaultChecked={evTypeOnline}
onChange={() => setEvTypeOnline(!evTypeOnline)}
/>
Online Festival / Awards Event
</label>
</div>
<Form.Group className="mb-3" controlId="runningYears">
<Form.Label>Running Years</Form.Label>
<Form.Control
type="text"
name="runningYears"
defaultValue={events?.runningYears}
placeholder=""
onChange={handleOnChange}
required
/>
</Form.Group>
<Form.Group className="mb-3" controlId="eventDescription">
<Form.Label>Event Description</Form.Label>
<textarea
type="text"
name="eventDescription"
placeholder=""
onChange={handleOnChange}
defaultValue={events?.eventDescription}
required
rows="3"
cols="88"
></textarea>
</Form.Group>
<Button type="submit">Submit</Button>
</form>
);
export default EventEdit;
backend, manual value update code.
app.put('/events/:id', async(req, res) => {
const id = req.params.id;
const query = {keyId:id}
const options = {upsert: true};
const updateDoc = { $set: { name: "Titas"} };
const result = await eventsCollection.updateOne(query, updateDoc, options);
res.json(result);
})

TypeError: editorState.getCurrentContent is not a function

I am trying to console the result from react draft wysiwyg and I am getting editorState.getCurrentContent is not a function. I am not sure where did I go wrong. Many thanks in advance and greatly appreciate any helps. Thanks
import React,{useState} from 'react'
import { render } from 'react-dom';
import { Editor } from 'react-draft-wysiwyg';
import {EditorState} from "draft-js";
import { stateToHTML } from "draft-js-export-html";
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
const AddBlog= () => {
const [editorState, setEditorState] = useState(
() => EditorState.createEmpty(),
);
const handleChange = (editorState) =>{
const contentState = stateToHTML(editorState.getCurrentContent())
// JSON.stringify(convertToRaw(editorState.getCurrentContent()))
console.log(contentState)
}
return (
<div className="container-fluid">
<div className="card-wrapper-tutorial">
<div className="card">
<div className="card-body">
<h4 className="card-title">New Code Snippet</h4>
<form autoComplete="off">
<div className="form-group">
<label htmlFor="title">Title</label>
<input id="title" type="text" className="form-control" placeholder="title" name="title" disabled = {disabled} onChange={handleChange} />
</div>
<div className="form-group">
<label htmlFor="body">Body</label>
<Editor
defaultEditorState={editorState}
onEditorStateChange={setEditorState}
wrapperClassName="wrapper-class"
editorClassName="editor-class"
toolbarClassName="toolbar-class"
onChange={handleChange}
/>
</div>
<div className="form-group">
<button type="submit" className="btn btn-primary btn-block">
{loading && <i className="fa fa-refresh fa-spin"></i>}
Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
)
}
export default AddBlog
You have the handleChange in two places which they don't belong
on the input's onChange, the callback for onChange would not
be an editorState but and input event e.
on the Editor
component, the callback for onChange would not be an editorState
also but a RawDraftContentState which is the string html.
You probably meant to place it in the onEditorStateChange for Editor:
<Editor
defaultEditorState={editorState}
onEditorStateChange={editorState => {
setEditorState(editorState);
handleChange(editorState);
}}
wrapperClassName="wrapper-class"
editorClassName="editor-class"
toolbarClassName="toolbar-class"
/>
or leaving the code as is and modifying the handleChange to expect RawDraftContentState
const handleChange = (rawDraftContentState) =>{
// no need for convertToRaw or stateToHtml anymore
console.log(rawDraftContentState)
}

Can I autofocus on the first field in a redux-form created using a loop?

I have created a React component using redux-form and am looking to autoFocus on the first field. The fields are created by looping through an object and creating a field for each item in that object. When I use autoFocus in the JSX is autoFocuses on the last field in the form (which makes sense).
Does anyone know how I can autoFocus on the first field in the form?
Here is my component:
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';
class BalanceForm extends Component {
constructor(props) {
super(props);
this.submitForm = this.submitForm.bind(this);
this.cancel = this.cancel.bind(this);
}
cancel() {
//not relevant
}
submitForm(e, values) {
//not relevant
}
render() {
return (
<div>
{this.props.balanceFormVisible &&
<div className="modal-background">
<div className="modal">
<form onSubmit={this.submitForm}>
{Object.keys(this.props.accounts).map((key) => {
return (
this.props.accounts[key].visible &&
<div key={this.props.accounts[key].name}>
<label className="form-label" htmlFor={this.props.accounts[key].name}>
{this.props.accounts[key].display}
</label>
<Field
name={this.props.accounts[key].name}
component="input"
type="number"
placeholder=""
autoFocus
/>
</div>
)
})}
<button type="submit">Submit</button>
<button onClick={ this.cancel } className="cancelbtn" >Cancel</button>
</form>
</div>
</div>
}
</div>
);
}
}
BalanceForm = reduxForm({form: 'balance'})(BalanceForm)
export default BalanceForm;
Thanks in advance :)
Solution to this was to conditionally render the form field. Thanks to Alexander Borodin for the inspiration...
{Object.keys(this.props.accounts).map((key, i) => {
console.log(key, i)
return (
this.props.accounts[key].visible &&
<div key={this.props.accounts[key].name}>
<label className="form-label" htmlFor={this.props.accounts[key].name}>
{this.props.accounts[key].display}
</label>
{(i === 0) ? (
<Field
name={this.props.accounts[key].name}
component="input"
type="number"
placeholder=""
autoFocus
/>
) : (
<Field
name={this.props.accounts[key].name}
component="input"
type="number"
placeholder=""
/>
)}
</div>
)
})}
Some of these either didn't compile or are a bit verbose. This worked for me:
{Object.keys(item)
.map((key, i) =>
<div className={`form-row ${key}`} key={key}>
<label>{key}</label>
<input value={item[key]}
type='text'
onChange={e => {
this._updateValue(key, e.target.value);
}}
autoFocus={i === 0}
/>
</div>
)}
Alternatively, if you hook in to ComponentDidMount, you can ask the DOM to focus the first existing field within the form.
Add a ref to the form
<form onSubmit={this.submitForm} ref='form'>
Use the ref to focus the element after mounting
componentDidMount() {
const firstInput = this.refs.form.querySelector('input')[0];
firstInput && firstInput.focus();
}
Try this:
{Object.keys(this.props.accounts).map((key, i) => {
return (
this.props.accounts[key].visible &&
<div key={this.props.accounts[key].name}>
<label className="form-label" htmlFor={this.props.accounts[key].name}>
{this.props.accounts[key].display}
</label>
<Field
name={this.props.accounts[key].name}
component="input"
type="number"
placeholder=""
{ (i === 0) ? 'autoFocus': ''}
/>
</div>
)
})}
I ran into an issue where autoFocus wasn't properly passing down from Field to the underlying component. Had to explicitly pass autoFocus in the props prop for Field.

react rerendering form causes focus/blur issue on state change

I have a form in a react component that has two change handlers, one for my two draftjs textareas, and one for my other text inputs:
onChangeEditor = (editorStateKey) => (editorState) => {
this.setState({ [editorStateKey]: editorState });
}
handleInputChange(event) {
event.preventDefault();
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
In my render method I have two views that I switch between depending on which view mode I am in, read or edit:
render () {
const Editable = () => (
<div className="editor">
<form className="editor-inner">
<h3>Redigerar: Anbudsbrev</h3>
<h4>Rubrik</h4>
<input type="text" key="text01" name="title" defaultValue={this.state.title} onBlur={this.handleInputChange} />
<h4>Text 1</h4>
<RichEditor editorState={this.state.editorState1} onChange={this.onChangeEditor('editorState1')} name="text01"/>
<h4>Citat</h4>
<input type="text" key="text02" name="quote01" defaultValue={this.state.quote01} onBlur={this.handleInputChange} />
<h4>Text 2</h4>
<RichEditor editorState={this.state.editorState2} onChange={this.onChangeEditor('editorState2')} name="text02" />
<EditorFooter {...this.props} submitForm={this.saveForm} />
</form>
</div>
);
const Readable = () => (
<div>
<h1 className="header66">{this.state.title}</h1>
<div className="text66">{this.state.text01}</div>
<div className="quote100">{this.state.quote01}</div>
<div className="text66">{this.state.text02}</div>
</div>
);
return (
<div>
{ this.props.isInEditMode ? <Editable /> : <Readable /> }
</div>
);
}
When I switch between inputs in my browser I have to click twice in order to get the focus on the right input.
I suspect that this is because a change is triggered on the "blur" event of each input, causing the form to rerender because state is changed. And when the form rerenders, it goes through the { this.props.isInEditMode ? <Editable /> : <Readable /> } which causes the input to lose focus.
The problem is that I don't know how to get around this.
I solved it myself.
It turns out that it was not a good idea to place the Editable and Readable inside of my component as I did. Instead I moved them out to their own components, and it works properly now.
class Editable extends React.Component {
render() {
return (
<div className="editor">
<form className="editor-inner">
<h3>Redigerar: Anbudsbrev</h3>
<h4>Rubrik</h4>
<input type="text" name="title" defaultValue={this.props.title} onChange={this.props.handleInputChange} />
<h4>Text 1</h4>
<RichEditor editorState={this.props.editorState1} onChange={this.props.onChangeEditor('editorState1')} name="text01" />
<h4>Citat</h4>
<input type="text" name="quote01" defaultValue={this.props.quote01} onChange={this.props.handleInputChange} />
<h4>Text 2</h4>
<RichEditor editorState={this.props.editorState2} onChange={this.props.onChangeEditor('editorState2')} name="text02" />
<EditorFooter {...this.props} submitForm={this.props.saveForm} />
</form>
</div>
);
}
};
class Readable extends React.Component {
render() {
return (
<div>
<h1 className="header66">{this.props.title}</h1>
<div className="text66">{this.props.text01}</div>
<div className="quote100">{this.props.quote01}</div>
<div className="text66">{this.props.text02}</div>
</div>
);
}
};