Disable / hide button depending on checkbox - reactjs

Is there a way to disable or hide a if the is checked ?
I would like to make CreateQuotation & TakeNotes buttons to hide or disable when the checkbox is not checked
Heres how my code looks like
const renderCheckbox = ({ input, label }) =>
<FormControlLabel
control={
<Checkbox
{...input}
checked={input.value ? true : false}
onCheck={input.onChange}
/>
}
label={label}
/>
const CreateReport = (props) => {
const { handleSubmit, pristine, submitting } = props;
return (
<div className="create-report-form-container mobile-padding">
<form onSubmit={handleSubmit}>
<div>
<Field name="quotation-checkbox" component={renderCheckbox} label="Quotation to do" />
</div>
<div>
<Button raised color="accent" label="CreateQuotation">
Create a Quotation
</Button>
<Button raised color="accent" label="TakeNotes">
Take some notes
</Button>
</div>
<Button raised color="accent" type="submit" label="send" disabled={pristine || submitting}>
Send
</Button>
</form>
</div>
);
};
export default reduxForm({
form: 'CreateReport',
enableReinitialize: true,
})(CreateReport);

I would add a constant variable like isActive which is toggling the checkbox state and to show and hide the Button you can do this in the return area:
{ isActive ? <Button>create Quotation & Take notes </Button> : null }
You can get the isActive state with calling a function in the state change:
<input
type="checkbox"
onChange={(event) => this.handleCheck(event)}
checked={true}
/>
constructor(props) {
super(props);
this.state = {
isActive: {}
};
this.handleCheck = this.handleCheck.bind(this);
}
handleCheck(event){
isActive = event.target.checked;
this.setState({ isActive: isActive });
}

class Rq extends Component {
constructor(){
super();
this.state = {
option: '',
isDisabled: true,
checked: true
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(){
this.setState({checked: !this.state.checked});
if (this.state.checked)
{
this.setState({isDisabled: false})
}
else
this.setState({isDisabled: true});
}
handleSubmit(e){
e.preventDefault();
if (this.state.isDisabled===false) {
alert('Form submitted')
} else
{
alert('form has not submitted');
}
}

Related

Checkbox validation using React JS

I am currently working on a form having checkboxes which has to be validated using react JS. I need it to show an error saying 'Please select atleast 2 checkbox' if less than 2 checkboxes are checked. I've tried using the if condition but its not working. I have referred a lot of of websites but couldn't come up with a proper solution. Please do help me.
MY CODE:
class App extends React.Component {
state = {
checkbox: "",
checkboxValid: false,
errorMsg: {},
};
validateForm = () => {
const { checkboxValid } = this.state;
this.setState({
formValid: checkboxValid,
});
};
updateCheckbox = (checkbox) => {
this.setState({ checkbox }, this.validateCheckbox);
};
validateCheckbox = () => {
const { checkbox } = this.state;
let checkboxValid = true;
let errorMsg = { ...this.state.errorMsg };
if (checkbox.checked < 2) {
checkboxValid = false;
errorMsg.checkbox = "Please select atleast 2 checkbox";
}
this.setState({ checkboxValid, errorMsg }, this.validateForm);
};
render() {
return (
<div>
<label htmlFor="checkbox">checkbox</label>
<ValidationMessage
valid={this.state.checkboxValid}
message={this.state.errorMsg.checkbox}
/>
<input
type="checkbox"
onChange={(e) => this.updateCheckbox(e.target.value)}
/>
Sports
<br></br>
<input
type="checkbox"
onChange={(e) => this.updateCheckbox(e.target.value)}
/>
Business
<br></br>
<input
type="checkbox"
onChange={(e) => this.updateCheckbox(e.target.value)}
/>
Health
<br></br>
<input
type="checkbox"
onChange={(e) => this.updateCheckbox(e.target.value)}
/>
Society
<br></br>
<div>
<button
className="button"
type="submit"
disabled={!this.state.formValid}
>
Submit
</button>
</div>
</div>
);
}
}
Define count in the state and update it based on the checkbox selection,
state = {
checkbox: "",
checkboxValid: false,
errorMsg: {},
selectedCheckBox: 0
};
Update Logic:-
updateCheckbox = ({ name, checked }) => {
this.setState(
(prev) => ({
checkbox: checked,
selectedCheckBox: checked
? prev.selectedCheckBox + 1
: prev.selectedCheckBox - 1
}),
this.validateCheckbox
);
};
Use the selectedCheckBox count in the state for validation
Completed Code:-
import React from "react";
import "./styles.css";
export default class App extends React.Component {
state = {
checkbox: "",
checkboxValid: false,
errorMsg: {},
selectedCheckBox: 0
};
validateForm = () => {
const { checkboxValid } = this.state;
this.setState({
formValid: checkboxValid
});
};
updateCheckbox = ({ name, checked }) => {
this.setState(
(prev) => ({
checkbox: checked,
selectedCheckBox: checked
? prev.selectedCheckBox + 1
: prev.selectedCheckBox - 1
}),
this.validateCheckbox
);
};
validateCheckbox = () => {
const { checkbox } = this.state;
let checkboxValid = true;
let errorMsg = { ...this.state.errorMsg };
if (this.state.selectedCheckBox < 2) {
checkboxValid = false;
errorMsg.checkbox = "Please select atleast 2 checkbox";
}
this.setState({ checkboxValid, errorMsg }, this.validateForm);
};
render() {
return (
<div>
<label htmlFor="checkbox">checkbox</label>
{/* <ValidationMessage
valid={this.state.checkboxValid}
message={this.state.errorMsg.checkbox}
/> */}
<input
type="checkbox"
name="business"
onChange={(e) => this.updateCheckbox(e.target)}
/>
Sports
<br></br>
<input
type="checkbox"
name="health"
onChange={(e) => this.updateCheckbox(e.target)}
/>
Business
<br></br>
<input
type="checkbox"
name="society"
onChange={(e) => this.updateCheckbox(e.target)}
/>
Health
<br></br>
<input
type="checkbox"
onChange={(e) => this.updateCheckbox(e.target)}
/>
Society
<br></br>
<div>
<button
className="button"
type="submit"
disabled={!this.state.formValid}
>
Submit
</button>
<br />
<b style={{ fontSize: "30px" }}>{this.state.selectedCheckBox}</b>
</div>
</div>
);
}
}
Working Demo - https://codesandbox.io/s/frosty-colden-8hdm4?file=/src/App.js:0-2160
One way to solve this is by having a different state for each checkbox. Set a name for each checkbox so that it can be access by e.target.name
Notice that the name of the input is the same as the state.
state = {
checkbox1: false,
checkbox2: false,
checkboxValid: false,
};
updateCheckbox = (e) => {
this.setState({ e.target.name: e.target.checked });
};
if(this.state.checkbox1 && this.state.checkbox2) {
//both are checked!
}
change input to
<input
name="checkbox1"
type="checkbox"
onChange={this.updateCheckbox}
checked={this.state.checkbox1}
/>

Can't clear input field after pressing button

class CategoryBox extends Component {
constructor(props) {
super(props);
this.state = {
newCategoryTitle: '',
errorMsg: null,
updateCategoryTitle: '',
};
this.handleCreateCategory = this.handleCreateCategory.bind(this);
this.handleUpdateCategory = this.handleUpdateCategory.bind(this);
}
...
...
handleUpdateCategory(e) {
e.preventDefault();
this.setState({
updateCategoryTitle: ''
});
}
render() {
return (
//...
<form>
<input
type={'text'}
className={styles.tabSmallField}
placeholder={ category.name }
onChange={(e) => { this.setState({ updateCategoryTitle: e.target.value }); }} />
<button type="submit" onClick={this.handleUpdateCategory}>Update</button>
</form>
//...
}
}
I want to clear input text field after pressing the button.
It looks like it enters into "handleUpdateCategory(e)" after pressing the button. But it does not clear the input field above the button.
How can I clear the input text field?
Answer is in comment.
It didn't clear because you never bind the state value to your <input>. Change it like this <input value={this.state.updateCategoryTitle} ...other props... />

Browser not previewing image that was previously uploaded

I have a component in React that is responsible for image preview. I also have an option for removing the image. I have noticed that if I have uploaded an image, and then removed it, that I can't preview it if I want to upload it again. Why is that happening?
This is my component:
class MediaPlaceholder extends Component {
constructor(props) {
super(props)
this.state = {
fileUrl: null
}
this.handleChange = this.handleChange.bind(this)
}
handleChange(event) {
this.setState({
fileUrl: URL.createObjectURL(event.target.files[0])
})
}
removeImage() {
this.setState((prevState) => {
URL.revokeObjectURL(prevState.fileUrl);
return {fileUrl: null};
});
}
render() {
const {classes} = this.props;
const {fileUrl} = this.state;
return (
<Paper className={classes.media}>
{fileUrl &&
<div className={classes.imageWrapper}>
<IconButton aria-label="Clear" className={classes.iconButton} onClick={() => this.removeImage()}>
<ClearIcon/>
</IconButton>
<img src={fileUrl} className={classes.image}/>
</div>
}
<input
accept="image/*"
className={classes.input}
id="upload-file"
type="file"
onChange={(event) => this.handleChange(event)}
/>
<label htmlFor="upload-file">
<Button component="span">
Add media...
</Button>
</label>
</Paper>
);
}
}

React couldn't read the state

I used the same function I got on a react native in a react app and it didn't work, looks like I couldn't access the sate although I defined it in the constructor, the goal is to push data to firebase, I tried with random strings and it definitely works, it's just when using the form that it crashes.
As you can see I'm using text components to take a look a the state on the HTML page :
import React, { Component } from 'react';
import fire from './config/Fire';
class Home extends Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
isOpen: false,
title: '',
description: '',
loading: true
};
}
handleChange(e) {
this.setState({ [e.target.name]: e.target.value });
}
saveData(e) {
e.preventDefault();
let title = this.state.title;
let description = this.state.description;
const { currentUser } = fire.auth();
fire
.database()
.ref(`/master/setup/`)
.push({ title, description })
.then(() => {
this.setState({ loading: false }).catch(error => {
console.log(error);
});
});
}
render() {
return (
<div>
<Container>
<Row>
<Col sm="2" lg="3" />
<Col sm="8" lg="6">
<h1>General Setup</h1>
<form>
<div class="form-group">
<label for="exampleInputEmail1">Title</label>
<input
value={this.state.title}
onChange={this.handleChange}
name="title"
class="form-control"
id="title"
placeholder="Enter event title"
/>
</div>
<div class="form-group">
<label for="exampleInputEmail1">Description</label>
<input
value={this.state.description}
onChange={this.handleChange}
name="description"
class="form-control"
id="description"
placeholder="Enter event description"
/>
</div>
<button onClick onClick={this.saveData} class="btn btn-primary">
Submit
</button>
</form>
<p>{this.state.title}</p>
<p>{this.state.description}</p>
<p>{this.state.loading.toString()}</p>
</Col>
<Col sm="2" lg="3" />
</Row>
</Container>
</div>
);
}
}
export default Home;
TypeError: Cannot read property 'state' of undefined
Please, someone, let me know what's going on with this code?
You can change saveData to an arrow function hence binding isn't required. This is an ES6 version, do something like below
saveData = e => {
e.preventDefault();
let title = this.state.title;
let description = this.state.description;
const { currentUser } = fire.auth();
fire.database().ref(`/master/setup/`)
.push({ title, description })
.then(() => {
this.setState({ loading: false})
.catch((error) => {
console.log(error);
})
});
}
You need to bind saveData in constructor.
this.saveData = this.saveData.bind(this);
You forgot to bind scope to saveData method.
Do it in constructor same as you bind it to handleChange method.
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.saveData = this.saveData.bind(this);
this.state = {
isOpen: false,
title: '',
description: '',
loading: true,
};
or
change saveData definition to one that uses arrow function syntax from ES6
saveData = (e) => {...function body as you already have it}
and parent scope will be bind for you by default

pristine function not working redux form

I started working with redux-form along with react-bootstrap. I have give validation in my form my custom validation is working fine but I have given pristine condition from this doc it is not working for me. below is my code for that let me know where I went wrong? do I need to add anything?
If anyone let me know what render field does for me?
const renderField = ({
input,
label,
type,
meta: { touched, error, warning }
}) => (
<div>
<label>{label}</label>
<div>
<input {...input} placeholder={label} type={type} />
{touched &&
((error && <span>{error}</span>) ||
(warning && <span>{warning}</span>))}
</div>
</div>
);
class Duplicate extends React.Component {
constructor(...args) {
super(...args);
this.state = {
open: false,
showModal: false
};
}
saveDuplicate = value => {
if ('[default]'.includes(value.duplicateName)) {
throw new SubmissionError({
duplicateName: 'User does not exist',
_error: 'Login failed!'
});
}
console.log('value on submit', value);
};
close = () => this.setState({ showModal: false });
openModal = () => this.setState({ showModal: true });
render() {
console.log('this props in duplicate', this.props);
const required = value => (value ? undefined : 'Required');
const { handleSubmit, pristine, reset, submitting } = this.props;
return (
<div className="scenario_btn">
<Button
onClick={this.openModal}
bsStyle="danger"
className="scenario_mangt"
>
Duplicate
</Button>
<Modal
aria-labelledby="modal-label"
show={this.state.showModal}
onHide={this.close}
>
<form onSubmit={handleSubmit(this.saveDuplicate)}>
<Field
name="duplicateName"
type="text"
component={renderField}
label="name"
validate={[required]}
/>
<div>
<button type="submit" disabled={submitting}>
Save
</button>
<button
type="button"
disabled={pristine || submitting}
onClick={reset}
>
Cancel
</button>
</div>
</form>
</Modal>
</div>
);
}
}
export default reduxForm({
form: 'duplicatForm' // a unique identifier for this form
})(Duplicate);

Resources