I am building a small feature that has a checkbox styled as slider that, when turned on and off, should display another component - BatchWidget. The way I have it currently set up, it works on initial page load, and then hides as intended. However, when I go to "toggle" it back on to show the component again, it does not work. Is there an easy solution to this?
const Slider = (props) => {
return (
<div className="slider-container">
<label className="switch">
<input type="checkbox" checked={props.checked} onClick= {props.showWidget} />
<span className="slider round" />
</label>
<p className="batch-slider-title"> Batch Widget </p>
</div>
);
};
const Settings = ({showSlider}) => {
return (
<div className="settings">
<i className="icon-gear" onClick={() => showSlider()} />
</div>
);
}
class WidgetContainer extends Component {
constructor() {
super();
this.state = {
checked: true,
isSliderDisplayed: false,
};
this.showWidget = this.showWidget.bind(this);
this.showSlider = this.showSlider.bind(this);
}
showWidget() {
this.setState({
checked: !this.state.checked,
});
}
showSlider() {
this.setState({
isSliderDisplayed: !this.state.isSliderDisplayed,
});
}
render() {
const displayBatchWidget = this.state.checked ? <BatchWidget /> : null;
const displaySlider = this.state.isSliderDisplayed ? <Slider checked={this.state.checked} showWidget={this.showWidget} /> : null;
return (
<div>
<Settings showSlider={this.showSlider} />
{displaySlider}
{displayBatchWidget}
</div>
);
}
}
When I try to debug, it shows:
Warning: Failed form propType: You provided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`. Check the render method of `Slider`.
I think it is self-explanatory.
I've changed the line with checkbox to:
<input type="checkbox" checked={props.checked} onChange= {props.showWidget} />
Now, the batchWidget should hide and show on each click.
Reactjs matrial ui table check box hide
first do
<Table selectable={false}>
<TableHeader displaySelectAll={false} adjustForCheckbox={false}>
this method hide table header check box
then do <TableBody displayRowCheckbox={false}>
it hide table body checkbox
it work perfect.
reactjs
Related
<FormGroup>
<div>
{this.props.diseases.map((disease, index) => (
<FormGroup>
<CustomInput
type="switch"
id="exampleCustomSwitch"
key={disease}
disease={disease}
onClick={(disease) => this.props.toggle(disease)}
label={disease}
/>
</FormGroup>
))
}
</div>
</FormGroup>
I want to be able to find out the state of the switch, whether it's switched on or off. Not sure how I'm able to do that? Am I to pass in a default value of some sort with 0 as off and 1 as on?
Presently, the switches are mapping appropriately from the array, but switching on or off only works for the first switch. So, if I click on any of the other switches, for some reason the first switch toggles.
For point #1,yYou can use e.target.checked to check the true/false status for a particular CustomInput; Check this stackblitz to see it work
For point #2 If you share your existing code, it will be easier to help with your specific scenario
relevant js:
class App extends Component {
constructor() {
super();
this.state = {
name: "World to React",
log: []
};
this.customInputSwitched.bind(this);
}
customInputSwitched(buttonName, e) {
let newStr = `we received ${e.target.checked} for ${buttonName}...`;
console.log(newStr);
let newLog = [...this.state.log, newStr];
this.setState({ log: newLog });
}
render() {
var testName = "modal for testing - click here";
return (
<div>
<Hello name={this.state.name} />
<p>Start editing to see some magic happen :)</p>
<Form>
<FormGroup>
<Label for="exampleCheckbox">Switches</Label>
<div>
<CustomInput
type="switch"
id="exampleCustomSwitch"
name="customSwitch"
label="Turn on this custom switch"
onChange={this.customInputSwitched.bind(this, "button1")}
/>
<CustomInput
type="switch"
id="exampleCustomSwitch2"
name="customSwitch"
label="Or this one"
onChange={this.customInputSwitched.bind(this, "button2")}
/>
<CustomInput
type="switch"
id="exampleCustomSwitch3"
label="But not this disabled one"
disabled
/>
<CustomInput
type="switch"
id="exampleCustomSwitch4"
label="Can't click this label to turn on!"
htmlFor="exampleCustomSwitch4_X"
disabled
/>
</div>
</FormGroup>
</Form>
{this.state.log}
</div>
);
}
}
UPDATE #1: In light of questioner's comment below
Few issues in your code at https://stackblitz.com/edit/react-rcqlwq
you have to instantiate Log in the state in the contstructor
the customInputSwitched function should pass the argument of the particular button, not a hard-coded 'button1' - so we add the index number of the disease
the ID of all the buttons can't be the same 'exampleCustomSwitch', so we just add the index number to ID
best practice in mapping as array is to include an index also, which has benefits (as shown in the next 2 points)
relevant working JS for your code/stackblitz:
class App extends Component {
constructor() {
super();
this.state = {
diseases: [
"Normal",
"Over inflated lungs",
"Pneumonia",
"Pneumothorax",
"Congestive cardiac failure",
"Consolidation",
"Hilar enlargement",
"Medical device",
"Effusion"
],
log: []
};
this.customInputSwitched.bind(this);
}
customInputSwitched(buttonName, e) {
let newStr = `we received ${e.target.checked} for ${buttonName}...`;
console.log(newStr);
let newLog = [...this.state.log, newStr];
this.setState({ log: newLog });
}
render() {
return (
<div>
<p>Start editing to see some magic happen :)</p>
<Form>
<FormGroup>
<Label for="exampleCheckbox">Switches</Label>
{this.state.diseases.map((disease, index) => {
//console.log(disease, index);
let idName = "exampleCustomSwitch"+index;
return (
<div key={index}>
<CustomInput
type="switch"
id={idName}
name="customSwitch"
label={disease}
onChange={this.customInputSwitched.bind(this, "button"+index)}
/>
</div>
);
}
)}
</FormGroup>
</Form>
{this.state.log}
</div>
);
}
}
I need to change the state of sibling components in my React App.
I use state and setstate
I need to change the state of sibling components. When loading the page, there must exist (visible in the page) <BkUser /> and when clicking "button id =" ds-visual "it must be deleted (<BkUser /> mustn't exist) and there must exist <BkDescanso />.
When you click on <BkSleep /> (in the div parent) you should remove <BkDescanso /> and show <BkUser />
This is the web.
There should never be <BkUser/> and <BkSleep> at the same time. <Bkuser /> is the blue block and <BkDescanso /> is the red block
This is my code:
Edit: I edit my original code because I fix the problem. This is the final OK Code. In the end the most important thing was the state conditional
{
this.state.usuario ? (<BkUser handleClick = {this.handleClick} usuario={this.state.usuario}/>): (<BkDescanso handleClick = {this.handleClick} usuario={this.state.usuario}/>)}
import React, { Component } from 'react';
class Header extends Component {
constructor(props) {
super(props);
this.state = {
usuario: true,
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({
usuario: !state.usuario
}));
//alert("Works button");
}
render(){
return (
<header className="header">
<div className="configuracion">
{
this.state.usuario
? (
<BkUser handleClick = {this.handleClick} usuario={this.state.usuario}/>
)
: (
<BkDescanso handleClick = {this.handleClick} usuario={this.state.usuario}/>
)}
<div className="content-btn">
<button id="config" className='btn btn--rounded'><span className="ico-configuracion"></span></button>
<button id="salir" className='btn btn--rounded'><span className="ico-exit"></span></button>
</div>
</div>
</header>
);
}
}
class BkUser extends Component{
render(){
return ((
<div className='usuario'>
<img src="../img//usuario.svg" alt="Imagen usuario"/>
<div className="content-usuario">
<span id="nm-usuario" className="h4">Hermione Jane Granger</span>
<span id="tp-usuario" className="h5">Supervisor</span>
</div>
<div className="content-descansos">
<div className="botones">
<button id="ds-visual" className='btn btn--rounded' onClick={this.props.handleClick}><span className="ico-visual"></span></button>
<button id="ds-admin" className='btn btn--rounded'><span className="ico-tiempo-administrativo"></span></button>
<button id="ds-otros" className='btn btn--rounded'><span className="ico-descanso"></span></button>
</div>
<div className="ds-actual">
<span id="ds-tipo">Administrativo</span>
<span id="ds-tiempo">00:08:47</span>
</div>
</div>
</div>
));
}
}
class BkDescanso extends Component {
render(){
return ((
<div className='usuario descanso' onClick={this.props.handleClick}>
<h3>Finalizar descanso</h3>
</div>
));
}
}
export default Header;
Right now handleClick works but always exist BkUser and BkDescanso. I need only one to exist. If you click on id = "ds-visual" the bkUser block should disappear and BkDescanso appear. Then if you click on div className = 'user rest' in BkUser there should only be BkDescanso.
I think that it is not able to know when it is true and when it is false to show or hide
Thanks a lot for the help.
You're missing two things:
First you have to pass the handleClick function to the BkUser component, and then you have to call it via this.props.handleClick.
...
<BkUser handleClick={this.handleClick} usuario={this.state.usuario} />
....
<button
id="ds-visual"
className="btn btn--rounded"
onClick={this.props.handleClick}
>
ds-visual
<span className="ico-visual" />
</button>
CodeSandbox here.
Read more here.
You can change the state of the siblings by passing a function from the parent via props into them.
In the end your siblings are the children of their parent.
You can read this articles on how to change the state of child components.
React js change child component's state from parent component
https://medium.freecodecamp.org/react-changing-state-of-child-component-from-parent-8ab547436271
An other thing you could look into would be React Redux.
I have a component in a React class in my Laravel project which is a simple form with one input field. It houses a phone number which I have retrieved from the database and passed back through the reducer and into the component as a prop. Using this, I have passed it through to the module as a prop which then populates the field with the currently saved value:
<OutOfOfficeContactNumberForm
show={props.showOutOfOffice}
value={props.outOfOfficeNumber}
handleChange={console.log("changed")}
/>
I have a handleChange on here which is supposed to fire a console log, but it only ever displays on page load. Here is my form module class:
class OutOfOfficeContactNumberForm extends React.Component {
render() {
const { show, value, handleChange } = this.props;
if(!show) return null;
return (
<div>
<p>
Please supply an Out of Office contact number to continue.
</p>
<InputGroup layout="inline">
<Label layout="inline" required={true}>Out of Office Contact Number</Label>
<Input onChange={handleChange} value={value} layout="inline" id="out-of-office-number" name="out_of_office_contact_number" />
</InputGroup>
</div>
);
}
}
export default (CSSModules(OutOfOfficeContactNumberForm, style));
The form is embedded in my parent component, as follows:
return (
<SectionCategoriesSettingsForm
isSubmitting={this.state.isSubmitting}
page={this.props.page}
show={this.props.show}
categories={this.props.categories}
submitSectionCategoriesSettings={this._submit.bind(this, 'add')}
updateSelectedCategories={this._updateSelectedCategories.bind(this)}
selectedCategoryIds={this.state.selectedCategoryIds}
storedUserCategories={this.props.selectedCategories}
outOfOfficeNumber={this.state.outOfOfficeNumber}
onUpdateContactNumber={this._updateContactNumber.bind(this)}
/>
);
In my componentWillReceiveProps() function, I set the state as follows:
if (nextProps.selectedCategories && nextProps.selectedCategories.length > 0) {
this.setState({
outOfOfficeNumber: nextProps.outOfOfficeNumber,
selectedCategoryIds: nextProps.selectedCategories.map(c => c.id)
});
}
I'm pretty sure the reason it's not changing is because it's pre-loaded from the state which doesn't change - but if I cannot edit the field how can I get it to register a change?
EDIT: Just to clarify there are also checkboxes in this form for the user to change their preferences, and the data retrieved for them is set the same way but I am able to check and uncheck those no problem
Changes:
1- onChange expect a function and you are assigning a value that's why, put the console statement inside a function and pass that function toOutOfOfficeContactNumberForm component , like this:
handleChange={() => console.log("changed")}
2- You are using controlled component (using the value property), so you need to update the value inside onChange function otherwise it will not allow you to change means input values will not be not reflect in ui.
Check example:
class App extends React.Component {
state = {
input1: '',
input2: '',
}
onChange = (e) => this.setState({ input2: e.target.value })
render() {
return(
<div>
Without updating value inside onChange
<input value={this.state.input1} onChange={console.log('value')} />
<br />
Updating value in onChange
<input value={this.state.input2} onChange={this.onChange} />
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app' />
I think the best way is when you get data from database put it to state and pass the state to input and remember if you want to see input changes in typing, use a function to handle the change and that function should change state value.
class payloadcontainer extends Component {
constructor(props) {
super(props)
this.state = {
number:1
}
}
render() {
return (
<div>
<input value={this.state.number} onChange={(e)=>this.setState({number:e.target.value})}></input>
<button onClick={()=>this.props.buyCake(this.state.number)}><h3>buy {this.state.number} cake </h3></button>
</div>
)
}
}
Trying to open datepicker on click of icon of react-datepicker component, I have gone through their docs and issues links but found that its not much useful.
<DatePicker
{...startDateOpts}
id='abc'
maxDate={moment()}
onChange={this.handleStartChange}
placeholderText='Start Date'
popoverAttachment={smallScreen ? 'bottom center' : undefined}
popoverTargetAttachment={smallScreen ? 'top center' : undefined}
popoverTargetOffset={smallScreen ? '0px 0px' : undefined}
/>
I tried from React-datepicker docs link but no luck.
Just wrap DatePicker with label. All click inside label call focus on input, that open calendar.
<label>
<DatePicker/>
</label>
If you want to programmatically open the datepicker or if you just don't want to use a <label> wrapper you can set a ref to the datepicker component and use setOpen(bool) to open it. Notice that since we're using refs, the component should be stateful.
Example:
openDatepicker = () => this._calendar.setOpen(true);
render() {
<Datepicker
{...datepickerProps}
ref={(c) => this._calendar = c} />
<img src={iconImg} onClick={this.openDatepicker} />
}
There is currently an open issue on the datepicker's Github stating that this is missing from the docs.
I have just finished that by that way,
svg icon has been imported by webpack
import IconCalendar from 'IconCalendar';
the render function in main component
render() {
const {reportSettings: {
dateTo
}} = this.props;
return (
<div id="date-picker">
<Label for="date-picker-1">Select Results date</Label>
<DatePicker todayButton={"Today"} dateFormat={Constants.DATE_FORMAT} customInput={(<ExampleCustomInput/>)} selected={dateTo} onChange={this.handleChange}/>
</div>
);
}
Secondary component that renders input field and icon
class ExampleCustomInput extends Component {
static propTypes = {
onClick: PropTypes.func,
value: PropTypes.string
}
render() {
const {value, onClick} = this.props;
return (
<div className="form-group">
<input type="text" className="form-control" value={value} onClick={onClick}/>
<IconCalendar className="date-picker-icon" onClick={onClick}></IconCalendar>
</div>
);
}
}
finally css helped me to display icon on input field
.date-picker-icon {
float: right;
margin-right: 6px;
margin-top: -30px;
position: relative;
z-index: 2;
}
After adding newer version of react-datepicker i.e. 0.30.0 i got props autofocus but, again I got problem that only worked for first time then i tried using ref like below
refs='startDate'
in datepicker then in this object i got
this.refs.startDate.deferFocusInput();
So i called it and I got date-picker open on click of icon
This can be achieved using ref as below:
const datepickerRef = useRef(null); // OR React.createRef(); if you are not using hooks
// OPENS UP THE DATEPICKER WHEN THE CALENDAR ICON IS CLICKED FOR THE INPUT FIELD
function handleClickDatepickerIcon() {
const datepickerElement = datepickerRef.current;
// console.log("datepickerElement = ", datepickerElement);
datepickerElement.setFocus(true);
}
<DatePicker
{...startDateOpts}
id="abc"
maxDate={moment()}
onChange={this.handleStartChange}
placeholderText="Start Date"
popoverAttachment={smallScreen ? "bottom center" : undefined}
popoverTargetAttachment={smallScreen ? "top center" : undefined}
popoverTargetOffset={smallScreen ? "0px 0px" : undefined}
ref={datepickerRef} // attach the ref
/>;
{/* CALENDAR ICON */}
<span className="calender-placment" onClick={() => handleClickDatepickerIcon()}>
<i className="fal fa-calendar-alt" />
</span>
Added in version 0.30.0, I think the customInput prop would allow you to do this. That way you could create your own input component and attach the onClick handler to the icon inside it.
#Jayant Patil I have achieved the functionality of opening react-datepicker on click of an icon.
This is how I did it.
I have created a wrapper component around the date picker and passed an id as props to it.
class DateRangePicker extends React.Component {
constructor(props, context) {
super(props, context);
// DatePicker is a controlled component.
// This means that you need to provide an input value
// and an onChange handler that updates this value.
}
render() {
return <DatePicker
id={this.props.id}
selected={this.props.selected}
onChange={this.props.onChange}
onChangeRaw={this.props.onChangeRaw}
onBlur={this.props.onBlur}
peekNextMonth={true}
showMonthDropdown={true}
showYearDropdown={true}
dropdownMode="select"
placeholderText="MM/DD/YYYY"
dateFormat="MM/DD/YYYY"
shouldCloseOnSelect={true}
defaultValue={null}
/>
}
}
export default DateRangePicker;
Then enclose your icon using a label and then pass the id.
<DateRangePicker
ref={'calendar1'}
id={'fromdate'}
dateFormat={gridAttributes.DEFAULT_DATE_FORMAT}
selected={this.state.fromDate}
onChange={this.handleDateChange.bind(this, 'fromDate')}
onChangeRaw={(e) => this.handleRawFromDateChange(e)}
onBlur={this.handleFromBlur.bind(this)}
peekNextMonth={true}
placeholderText={gridAttributes.DEFAULT_DATE_FORMAT}
showMonthDropdown={true}
showYearDropdown={true}
defaultValue={null}
className="calendar1"
/>
<label className="icon iconCalendar calendar" style={{ fontSize: '20px' }} htmlFor='fromdate' />
This works without affecting any functionality unlike when only enclosing the icon with label as said by #tre
<label>
<DatePicker/> </label>
causes the calendar to be in open and can be closed only when we click outside the calendar.
I don't know but none of these solutions worked for me. So made the following one:
openDatepicker = (e) => {
// find date picker input element
const inputElement = e.target.closest('.my-wrapper-class')?.querySelector('input')
return inputElement?.click();
}
The accepted answer is having some issues in that, like ->
When user select the date, the calender is not closing on date select, as the <label> trying to setOpen = true again so even after selecting the date, the claendar still open.
How to overcome this issue? see below the simple answer ->
this.state = {
openCalendar : false,
date : new Date()
}
handleChange = date => this.setState({ setDate : date });
render(){
return(
<label>
<DatePicker
selected={this.state.date}
onFocus={() => this.setState({ openCalendar: true })}
onChange={this.handleDateChange}
open={this.state.openCalendar}
/>
//you can add any icon here and on click that, the date will work as expected.
<svg/> //add any icon you want
</label>
)
}
There is a litter bug like this:
There are three radioGroup , we call it A , B, C.
A:Has 2 radios ,it will control to render B or render C.
B:Has 4 radios,default B-1(the first radio of B)
C:Has 10 radios,default C-1(this first radio of C)
when I choose A-1,the B is rendered,the default is B-1.
Then I choose B-2,then I choose A-2.
The Error come out,I found the C-2 is Checked!
But I didn`t click the C-2 at all.
So Why this happened? How could I fixed it?
class Tanx extends React.Component{
constructor() {
super();
this.subMit = this.subMit.bind(this);
this.setData = this.setData.bind(this);
this.setGreatspec = this.setGreatspec.bind(this);
this.setPlatform = this.setPlatform.bind(this);
this.state = {
platform:"PC",
create_spec:"99",
ad:null
};
}
setGreatspec(val) {
this.setState({
create_spec:val
})
}
setPlatform(val) {
console.log(this);
this.setState({
platform:val
});
}
setData(val){
this.setState({
ad:val
})
}
subMit() {
let create_spec = this.state.create_spec;
let platform = this.state.platform;
let self = this;
console.log(this.state);
// $.ajax({
// url:"/req/gdt/"+platform+"/"+create_spec,
// type:'get',
// success:function(res){
// // var ad = res.msg&&res.msg.seatbid[0].bid[0];
// var ad = res.msg
// self.setData(ad);
// console.log(res);
// },
// error:function(err){
// console.log(err);
// }
// })
}
render() {
var ad = this.state.ad;
if(ad){
var ad_html = (<div className="col-lg-4">
<pre style={{background:"#eee",padding:"10px",maxHeight:"500px",overflow:"scroll"}}>
<code style={{color:"green",fontSize:"14px"}}>
{JSON.stringify(ad,null,"\t")}
</code>
</pre>
</div>);
}else{
var ad_html = "";
}
var platform = this.state.platform;
if(platform==='PC'){
var radio_box = <RadioBox titles={['99','23','12','2']} name="create_spec_moblie" getVal={this.setGreatspec} />
}else{
var radio_box = <RadioBox titles={['80','207','208','212','147','148','149','150','79','58','59','70','113','114','10','28','31','35','69','65','133','134']} name="create_spec_moblie" getVal={this.setGreatspec} />
}
return(
<div className="row">
<div className="col-lg-3">
<FormGroup name="Platform">
<RadioBox titles={['PC','Mobile']} name="platform" getVal={this.setPlatform} />
</FormGroup>
<FormGroup name="Create_spec">
{radio_box}
</FormGroup>
<button className="btn btn-info btn-lg" onClick={this.subMit}>Submit</button>
</div>
{ad_html}
</div>
)
}
}
You need to understand the React internals for this. React needs a way to identify the "uniqueness" of a component. In your example you're using RadioBox with the same name and injecting in the parent component output. In the end, what react sees is quite the same markup but with only the titles property beeing changed, so internally, React will only change the props passed to the component (using the same component whatsoever).
So, in the end your component outputs one of the following markups:
<div className="row">
<div className="col-lg-3">
<FormGroup name="Platform">
<RadioBox titles={['PC','Mobile']} name="platform" getVal={this.setPlatform} />
</FormGroup>
<FormGroup name="Create_spec">
<RadioBox titles={['99','23','12','2']} name="create_spec_moblie" getVal={this.setGreatspec} />
</FormGroup>
<button className="btn btn-info btn-lg" onClick={this.subMit}>Submit</button>
</div>
<AdHTML here... />
</div>
or
<div className="row">
<div className="col-lg-3">
<FormGroup name="Platform">
<RadioBox titles={['PC','Mobile']} name="platform" getVal={this.setPlatform} />
</FormGroup>
<FormGroup name="Create_spec">
<RadioBox titles={['80','207','208','212','147','148','149','150','79','58','59','70','113','114','10','28','31','35','69','65','133','134']} name="create_spec_moblie" getVal={this.setGreatspec} />
</FormGroup>
<button className="btn btn-info btn-lg" onClick={this.subMit}>Submit</button>
</div>
<AdHTML here... />
</div>
As you can see, either version you choose, the difference is the titles attribute passed to the second RadioBox component. i.e. titles={[a, different, set, of, titles]}
So what the library determines in this case is that you're using the same RadioBox component with a slight change - i.e. title - and uses the same cached component and re-renders it with the different parameter. The internal state of the component, thus, remains unchanged.
But you actually need the same component being rendered uniquely for each of your cases. So you have to pass an id parameter in each case, and (maybe) remove the name attribute since it's completely useless.
So in each of your case you have to pass an id parameter that should be unique.
<RadioBox title={[B, checkbox, titles]} id="b-checkbox" />
and
<RadioBox title={[C, checkbox, titles]} id="c-checkbox" />