In my react app I have generic Input component:
class Input extends Component {
constructor(props) {
super(props);
if (props) {
this.state = {
elementType: props.elementType,
elementConfig: props.elementConfig,
cssClasses: props.cssClasses,
};
}
this.changeValue = this.changeValue.bind(this);
}
render() {
switch (this.state.elementType) {
case ('input'):
inputElement = <input
className={inputClasses.join(' ')}
{...this.state.elementConfig}
value={this.props.getValue() || ''}
onChange={this.changeValue} />;
break;
}
return (
<div className={requiredClass}>
{inputElement}
<span className={'text-danger'}>{requiredMessage}</span>
<span className={'text-danger'}>{errorMessage}</span>
</div>
);
}
}
Next, I use this group of inputs with react-formsy:
<Formsy>
<Input
requiredMessage='required'
required
name="checkbox"
elementType="input"
elementConfig={{ type: 'checkbox', id: 'check1'}}
cssClasses={['custom-input']}
/>
<button type="button" disabled={!this.props.canSubmit}></button>
</Formsy>
This checkboxes should be required,
until they are checked, the button must be inactive.
but the problem is that I can't check the checkboxes.
I am new in react. Where is my mistake?
Related
I am trying to control my radio buttons with state so that i can add an active class for a radio button when it is clicked. Im stuck now because i need to double click to make the radio button change and after they changed once, i cant get anymore console output. Can someone see what is wrong?
import React, { Component } from 'react'
class CustomRadio extends Component {
constructor(props) {
super(props);
this.state = {
name:'',
id:'',
value:'',
onChange:'',
label:'',
validationMsg:'',
rbValue:'',
checked:''
};
}
onSelect = (e) => {
this.setState({
rbValue: e.target.value
});
//console.log(this.state.rbValue);
console.log(e.target.value);
console.log(this.props.checked);
}
// setClass = () => {
// if (this.state.rbChecked === true)
// return "active"
// else
// return "inactive"
// }
render() {
//let rbActiveClass = this.setClass();
return (
// <div className={`form-item custom-radio ${rbActiveClass}`}>
<div className={`form-item custom-radio`}>
{this.props.label &&
<label htmlFor={this.props.id}>
{this.props.label}
</label>
}
<input
type="radio"
id={this.props.id}
name={this.props.name}
value={this.props.value}
checked={this.state.rbValue === this.props.checked}
//defaultChecked={this.props.defaultChecked}
onChange={this.onSelect.bind(this)}
/>
{this.props.validationMsg &&
<span className="validation-message">
{this.props.validationMsg}
</span>
}
</div>
)
}
}
export default CustomRadio
just change component constructor:
class CustomRadio extends Component {
constructor(props) {
super(props);
this.state = {
//...
rbValue:props.checked,
//...
};
}
and also input component:
<input
//...
checked={this.state.rbValue}
//...
/>
Hello I am trying to render my PostOnWall component I made using an onClick function. The goal that every time someone clicks the button handleClick will render one new component on the screen each time. So if I click the button three times i should see three PostOnWall components rendered on my screen. Please tell me what I am doing wrong.
class Textbox extends Component {
constructor(props) {
super(props);
this.handleClick.bind(this);
this.state = {
textArea: "",
text: "",
show: false,
curTime : new Date().toLocaleString(),
};
}
handleChange(event) {
const myValue = event.target.value;
this.setState({
textArea: myValue
})
console.log(this.state)
}
handleClick= () => {
this.setState({text:this.state.textArea,
show: !this.state.show});
return (
<div>
{this.state.show && <PostOnWall PostOnWall={this.props.PostOnWall} text={this.state.text} time={this.state.curTime}/>}
</div>
);
}
showNewPost
render() {
return (
<div>
<textarea className="Textbox"
rows="2" cols="30"
type = "text"
onChange={this.handleChange.bind(this)}
value={this.state.textArea} >
</textarea>
<button className="postbutton" onClick={this.handleClick.bind(this)}>Post</button>
</div>
);
}
}
export default Textbox;
That should do the trick for you;
import React, { Component } from 'react';
class Textbox extends Component {
constructor(props) {
super(props);
this.handleClick.bind(this);
this.state = {
textArea: '',
text: '',
show: false,
curTime: new Date().toLocaleString(),
};
}
handleChange = (event) => {
const myValue = event.target.value;
this.setState({
textArea: myValue
});
}
handleClick= () => {
this.setState({
text: this.state.textArea,
show: !this.state.show
});
}
render() {
return (
<div>
<textarea
className="Textbox"
rows="2"
cols="30"
type="text"
onChange={this.handleChange.bind(this)}
value={this.state.textArea}
/>
<button
className="postbutton"
onClick={this.handleClick}
type="button"
>
Post
</button>
{
this.state.show &&
<PostOnWall
PostOnWall={this.props.PostOnWall}
text={this.state.text}
time={this.state.curTime}
/>
}
</div>
);
}
}
You should use the function called on click to change the state only. Then render (or not) the PostOnWall component based on the state value.
you need to add state which increase on click and then render the component depending on how many time the button is clicked. here the codeSandbox for what you are trying to achieve.
I am trying to update my state by using a click function. However for some reason it is not updating. Could someone please explain to me what I am doing wrong?class Textbox extends
Component {
constructor(props) {
super(props);
this.handle = this.handle.bind(this);
this.state = {
text: 'jkjkljkljl'
}
}
handle(event) {
const myValue = event.target.value;
this.setState({
text: myValue
})
console.log(this.state)
}
render() {
return (
<div>
<textarea className="Textbox" rows="2" cols="30" type = "text" >
</textarea>
<button className="postbutton" onClick={this.handle.bind(this)}>Post</button>
<h1>{this.state.text}</h1>
</div>
);
}
}
export default Textbox;
Here is an updated version of your code that works.
Issue was that you were trying to set the value of the button to the state.
What you should do is setup textarea as a controlled input (have value and onChange setup as I did below) and use that value on click.
class Component extends React.Component {
constructor(props) {
super(props);
this.state = {
textArea: "",
text: "jkjkljkljl"
};
}
handle(event) {
console.log(event);
this.setState({
text: this.state.textArea
});
console.log(this.state);
}
handleChange(event) {
this.setState({ textArea: event.target.value });
}
render() {
return (
<div>
<textarea
className="Textbox"
rows="2"
cols="30"
value={this.state.textArea}
onChange={this.handleChange.bind(this)}
/>
<button className="postbutton" onClick={this.handle.bind(this)}>
Post
</button>
<h1>{this.state.text}</h1>
</div>
);
}
}
It seems you are trying to handle a form using React/JSX. There are great libraries for this purpose (React Forms).
This is the proper code:
class App extends React.Component {
constructor(props) {
super(props);
this.handle = this.handle.bind(this);
this.state = {
text: 'Static'
}
}
handleOnChange(event) {
this.setState({text: event.target.value});
}
handleSubmit(event) {
if (event.keyCode == 13) return this.sendData();
}
render() {
return (
<div>
<form onKeyUp={this.handleOnChange}>
<textarea className="Textbox"
rows="2" cols="30" type="text"
>
</textarea>
<button className="postbutton"
onClick={this.handleSubmit.bind(this)}>
Post
</button>
</form>
<h1>{this.state.text}</h1>
</div>
);
}
}
React.render(<App />, document.getElementById('app'));
In your example, you are binding the state to the root of the button and not the textarea. If you want a static example (whereas the above code changes as you type), you may simply handle the enter key via if (event.keyCode == 13) return this.sendData() and remove the onChange.
I have a question about why does not the "onClick" function work? It will only receive "You are not old enough!", when i hit the button. I use a input field.
import React, { Component } from 'react';
class App extends Component {
constructor() {
super();
this.state= {
term: 'write a number'
}
this.change = this.change.bind(this);
}
change = (event) => {
this.setState({term: event.target.value >= 18 ? <p>You are old enough!
</p> : <p>You are not old enough!</p>});
}
render() {
return (
<div style={{textAlign : "center"}}>
<input type="text"></input><br></br>
<p>Result</p><br></br>
{this.state.term}
<button type="submit" onClick={this.change}>Submit</button>
</div>
);
}
}
export default App;
If you want to validate the input on click, store the value of the input in state.
class App extends Component {
constructor() {
super();
this.state = {
term: 'write a number',
value: ''
};
}
handleChange = event => {
this.setState({
value: event.target.value
});
};
validate = () => {
this.setState({
term:
parseInt(this.state.value) >= 18
? 'You are old enough!'
: 'You are not old enough!'
});
};
render() {
return (
<div style={{ textAlign: 'center' }}>
<input
type="text"
onChange={this.handleChange}
value={this.state.value}
/>
<br />
<p>Result</p>
<br />
<p>{this.state.term}</p>
<button type="submit" onClick={this.validate}>
Submit
</button>
</div>
);
}
}
You can create a handler for the input and when you click in the button you get the value from the state.
Check it out my approach.
class App extends React.Component {
state = {
age: null,
term: 'write a number'
}
onClick = () => {
if(this.state.age) {
const output = this.state.age >= 18 ?
<p>You are old enough!</p> :
<p>You are not old enough!</p>
this.setState({
term: output
});
}
onInputHandler = (event) => {
this.setState({age: event.target.value})
}
render() {
return (
<div style={{textAlign : "center"}}>
<input type="text" onChange={e => this.onInputHandler(e)}></input><br></br>
<p>Result</p><br></br>
<button onClick={this.onClick}>Submit</button>
</div>);
}
}
So I am organizing my React project and I am creating a form, which I would like to give the user the ability to individually edit and post values for a particular item in the form, or alternatively check a box that will let them edit multiple fields at once, and hit a save button to load the whole form. So I know my parent component is going to need an "isEditingAll" type of state and my child components (each field) will have to display their own "isEditing" state for when it can save its value up as an individual post. Currently I have the following code in the render of my child:
render(){
return(
<span className="displayList">
{this.state.isEditing ? '' : <span className="clickMe" onClick={this.onClickEdit}>{this.state.displayText}</span>}
{this.state.isEditing ? <span><input name="inputValue" className="inputValue" value={this.state.displayText} type="text" onKeyPress={this.handleKeyPress} onChange={this.onTextChanged}/></span> :''}
{this.state.isEditing ? <button className="saveMe" onClick={this.onSaveEdit}>Save</button> :''}
</span>
)
}
This allows me to view values when !isEditing and edit values when isEditing, and there is a save button. But when someone checks the box in a parent, I need it to override this value. Is the best option to add a prop value that is passed in from the parent state for isEditingAll prop that will connect my parent isEditingAll? Then I would be able to hide the save button when editing entire form. I just fear I am adding a lot of complexity to the child component. Let me know your thoughts and if I may be missing some possible options for this logic? Thanks in advance.
No problem, you can do it if you need.
Reactjs is a very flexible library that allows developer do lots of crazy things.
In this scenario, I was imagining you could do something like this.
MainForm.js
import React, { Component } from 'react';
import InputForm from './InputForm';
class MainForm extends Component {
constructor(props) {
super(props);
this.state = {
multipleChecked: false,
fields: [{name: 'name', value: 'Alfred'}, {name: 'lastName', value: 'Smith'}],
}
}
onMultipleClick(e) {
this.setState({multipleChecked: e.target.checked});
}
onSaveIndividualEdit(name, value) {
let fieldsChanged = this.state.fields;
fieldsChanged.forEach(field => {
if (name == field.name) {
field.value = value;
return true;
}
});
this.setState({fields: fieldsChanged});
}
render() {
return (
<div>
<input type="checkbox" onClick={this.onMultipleClick.bind(this)}>Multiple edit</input>
{this.state.fields.map(field =>
<InputForm editingMultiple={this.state.multipleChecked} name={field.name} value={field.value} onSaveIndividualEdit={this.onSaveIndividualEdit.bind(this)} />
)}
</div>
);
}
}
export default MainForm;
InputForm.js
import React, { Component, PropTypes } from 'react';
class InputForm extends Component {
constructor(props) {
super(props);
this.state = {
isEditing: false,
editingMultiple: false,
displayText: ''
}
}
componentWillReceiveProps(nextProps) {
if (nextProps !== undefined) {
if (nextProps['value'] !== undefined) {
this.setState({displayText: nextProps.value});
}
if (nextProps['isEditing'] !== undefined) {
this.setState({isEditing: nextProps.isEditing});
}
if (nextProps['editingMultiple'] !== undefined) {
this.setState({editingMultiple: nextProps.editingMultiple});
}
}
}
onTextChanged(e) {
this.setState({displayText: e.target.value});
}
onClickEdit() {
this.setState({isEditing: true});
}
onSaveEdit() {
this.props.onSaveEdit(this.props.name, this.state.displayText);
this.setState({isEditing: false});
}
render() {
return (
<div>
<span className="displayList">
{this.state.isEditing ? '' : <span className="clickMe" onClick={() => this.onClickEdit()}>{this.state.displayText}</span>}
{this.state.isEditing ? <span><input type="text" onChange={this.onTextChanged.bind(this)} value={this.state.displayText}/></span> :''}
{this.state.isEditing && !this.state.editingMultiple ? <button type="button" onClick={() => this.onSaveEdit()}>Save</button> :''}
</span>
</div>
);
}
}
InputForm.propTypes = {
name: PropTypes.string,
value: PropTypes.string,
editingMultiple: PropTypes.bool,
onSaveEdit: PropTypes.func
};
export default InputForm;
I hope it can help you to make you go ahead!
Regards,
Renan