I just started using React.js, and I'm just not sure whether there is a special way to get the value of a textbox, returned in a component like this:
var LoginUsername = React.createClass({
render: function () {
return (
<input type="text" autofocus="autofocus" onChange={this.handleChange} />
)
},
handleChange: function (evt) {
this.setState({ value: evt.target.value.substr(0, 100) });
}
});
As described in documentation You need to use controlled input. To make an input - controlled you need to specify two props on it
onChange - function that would set component state to an input value every time input is changed
value - input value from the component state (this.state.value in example)
Example:
getInitialState: function() {
return {value: 'Hello!'};
},
handleChange: function(event) {
this.setState({value: event.target.value});
},
render: function() {
return (
<input
type="text"
value={this.state.value}
onChange={this.handleChange}
/>
);
}
More specifically about textarea - here
just update your input to the value
var LoginUsername = React.createClass({
getInitialState:function(){
return {
textVal:''
}
},
render: function () {
return (
<input type="text" value={this.state.textVal} autofocus="autofocus" onChange={this.handleChange} />
)
},
handleChange: function (evt) {
this.setState({ textVal: evt.target.value.substr(0, 100) });
}
});
Your text input value is always in the state and you can get the same by this.state.textVal
Related
I'm trying to get the value of input onClick(not onChange) and I got really confused.
(the function should take user input and multiply it by 5)
var Multiply = React.createClass({
getInitialState: function(){
return {number: '-'}
},
multiply: function(a){
return (a * 5);
},
handleChange: function(e) {
this.setState({ number: e.target.value });
},
handleClick: function(e) {
this.multiply(this.state.number);
},
render: function () {
return (
<div>
<p>multiply by 5!</p><br />
<textarea onChange={this.handleChange}>
</textarea><br/>
<button onClick={this.handleClick}>Submit</button>
<p>result:</p> {this.state.result}
</div>
);
}
});
ReactDOM.render(
<Multiply/>,
document.getElementById('root')
);
Here is a link to code:
http://codepen.io/polinaz/pen/MmezZy?editors=0010
What's wrong with my logic? Will really appreciate a good explanation!
Thank you
When you click the button, it multiples the number by 5, but then you don't do anything with that multiplied number (the result). In your handleClick function you need something like this:
handleClick: function(e) {
this.setState({result: this.multiply(this.state.number)});
}
I added result to the state, and added a result variable into the multiply function so you can store it in the state. Please look below:
var Multiply = React.createClass({
getInitialState: function(){
//added result to the initial state here
return {number: '-',
result: 0}
},
multiply: function(a){
//added result var here, and set the state to accept this result
var result = a * 5;
this.setState({result: result});
},
handleChange: function(e) {
this.setState({ number: e.target.value });
},
handleClick: function(e) {
this.multiply(this.state.number);
},
render: function () {
return (
<div>
<p>multiply by 5!</p><br />
<textarea onChange={this.handleChange}>
</textarea><br/>
<button onClick={this.handleClick}>Submit</button>
<p>result:</p> {this.state.result}
</div>
);
}
});
ReactDOM.render(
<Multiply/>,
document.getElementById('root')
);
This is for a react JS project (jsfiddle). The textbox should update with the true/false checked value of the checkbox, but it does not do so. Can someone explain why?
var AutoGenerateCheckbox = React.createClass ({
getInitialState: function() {
return {checked: false};
},
update() {
this.state.checked = !this.state.checked;
alert(this.state.checked);
this.props.onUpdate(this.state.checked);
},
render() {
return (
<input type="checkbox" checked={this.state.checked} onChange={this.update} />
);
}
});
var TBox = React.createClass({displayName: 'TextBox',
render: function() {
return (
<div>
Checkbox value: {this.props.data}
</div>
);
}
});
var KApp = React.createClass({
getInitialState: function() {
return {autoChecked: false};
},
handleAutogenChange: function(val) {
alert('handleAutogenChange:' + val);
this.setState({autoChecked : val});
},
render: function() {
return (
<div>
<AutoGenerateCheckbox onUpdate={this.handleAutogenChange}/>
<TBox data={this.state.autoChecked}/>
</div>
);
}
});
ReactDOM.render(
<KApp />,
document.getElementById('content')
);
The reason you don't see anything printed out is because you are trying to print a boolean value here
<div>
Checkbox value: {this.props.data}
</div>
try
<div>
Checkbox value: {this.props.data.toString()}
</div>
instead.
As an extra tip, you don't really need to hold the state of the checkbox in both its own state and its parent component's state. You really only need to have it in the parent component's state.
See the fiddle I made.
React is not determining the Boolean value to be printable information, try this instead:
<div>
Checkbox value: {this.props.data.toString()}
</div>
I have created the form validation with a structure like this
var Signin = React.createClass({
render: function() {
return (
<Form>
<Input type="text" name="email" labelName="Email" rules="isEmail" error:"Email not valid" />
<Input type="password" name="password" labelName="Password" rules="isLength:6" error:"Passowrd not valid"/>
</Form>
);
}
});
because, for example, the "Email" input will be used in different part of application, I would avoid to add the same attributes (name, type, labelName, rules and error) every time. So I would create something like this
var InputEmail = React.createClass({
render: function () {
return (
<Input type="text" name="email" labelName="Email" rules="isEmail" error="Email not valid"/>
)
}
});
var InputPassword = React.createClass({
render: function () {
return (
<Input type="password" name="password" labelName="Password" rules="isLength:6" error="Passwordnot valid"/>
)
}
});
So the Signin Component should be
var Signin = React.createClass({
render: function() {
return (
<Form>
<InputEmail />
<InputPassword />
</Form>
);
}
});
but in this way, I get two errors:
I can't find anymore in the Form the props.name of Input because
there isn't in InputEmail;
in the render function of Input the state is null
How could I create a reausable/inherits components? I failed using both the composition pattern and the mixins
I added my full code: Form
var Form = React.createClass({
getInitialState: function () {
return {
isValid : false,
isSubmitting: false
}
},
componentWillMount: function(){
this.model = {};
this.inputs = {};
this.registerInputs(this.props.children);
},
registerInputs: function(children){
React.Children.forEach(children, function (child) {
if (child.props.name) {
child.props.attachToForm = this.attachToForm;
child.props.detachFromForm = this.detachFromForm;
child.props.validate = this.validate;
}
if (child.props.children) {
this.registerInputs(child.props.children);
}
}.bind(this));
},
attachToForm: function (component) {
this.inputs[component.props.name] = component;
this.model[component.props.name] = component.state.value;
this.validate(component);
},
detachFromForm: function (component) {
delete this.inputs[component.props.name];
delete this.model[component.props.name];
},
validate: function (component) {
var isValid = true;
// validation code
component.setState({
isValid: isValid,
}, this.validateForm);
},
validateForm: function () {
var formIsValid = true;
var inputs = this.inputs;
Object.keys(inputs).forEach(function (name) {
if (!inputs[name].state.isValid) {
formIsValid = false;
}
});
this.setState({
isValid: formIsValid
});
},
updateModel: function (component) {
Object.keys(this.inputs).forEach(function (name) {
this.model[name] = this.inputs[name].state.value;
}.bind(this));
},
submit: function (event) {
event.preventDefault();
this.setState({
isSubmitting : true
});
this.updateModel();
console.log(this.model);
},
render: function () {
return (
<form className="ui form" onSubmit={this.submit}>
{this.props.children}
<button className="ui button" type="submit" disabled={this.state.isSubmitting}>Accedi</button>
</form>
);
}
});
Input
var Input = React.createClass({
getInitialState: function(){
return {
value : this.props.value || "",
isValid: true
}
},
setValue: function (event) {
this.setState({
value: event.target.value
}, function () {
this.props.validate(this);
}.bind(this));
},
componentWillMount: function () {
if (this.props.required) {
this.props.validations = this.props.validations ? this.props.validations + ',' : '';
this.props.validations += 'isLength:1';
}
// ERROR: TypeError: this.props.attachToForm is not a function
this.props.attachToForm(this);
},
componentWillUnmount: function () {
this.props.detachFromForm(this);
},
render: function () {
var className = "field";
if(this.props.className){
className += " " + this.props.className;
}
if(this.props.required){
className += " required";
}
var Label;
if(this.props.labelName){
Label = (<label htmlFor={this.props.name}>{this.props.labelName}</label>);
}
var Error;
if(!this.state.isValid){
Error = (<div className="ui">{this.props.error || this.props.name + " not valid"}</div>);
};
return (
<div className={className}>
{Label}
<input type={this.props.type || "text"} id={this.props.name} name={this.props.name} onChange={this.setValue} value={this.state.value} />
{Error}
</div>
);
}
});
With this works
ReactDOM.render(
<Form>
<Input type="text" name="email" labelName="Email" rules="isEmail" error:"Email not valid"/>
</Form>,
document.getElementById('app')
);
In this way I get:
"TypeError: this.props.attachToForm is not a function
this.props.attachToForm(this);"
ReactDOM.render(
<Form>
<InputEmail/>
</Form>,
document.getElementById('app')
);
P.S: I tried to add this code on jsfiddle but I get "!TypeError: can't define property "attachToForm": Object is not extensible"
jsfiddle
There are 2 main issues with your setup:
Your <Form> is set up in such a way, that the children of the form need to have props, otherwise it does not work.
The <InputEmail> wrapper is incomplete. It needs to pass along all props to the <Input>, including the Form functions passed down.
Ad 1: Fix the form, to ensure validation methods are added
The reason you get the error is because the children of your <Form> need to have props.name. It then registers the functions of the form (including attachToForm), by adding them to the children. This is done in the method registerInputs().
In the original variant, the <Input> component has props, so all goes well.
In the adapted variant, the wrapper <InputEmail> no longer has props, so the attachToForm() and other functions are not added to props, and you get the error when the <Input> tries to invoke the function.
Simplest way to fix this: add at least 1 prop in the render function, and check this in the registerInputs(), e.g.:
ReactDOM.render(
<Form>
<InputEmail initialValue={'name#domain.com'}/>
</Form>,
document.getElementById('app')
);
And in registerInputs(), change the line:
if (child.props.name) {
to:
if (child.props.initialValue) {
2. Extend <InputEmail> wrapper to pass down functions as well
Simplest way to do this is to add {...this.props}, like this:
var InputEmail = React.createClass({
render: function () {
return (
<Input {...this.props}
type="text" name="email" labelName="Email" rules="isEmail" error="Email not valid"/>
)
}
});
That way, the functions passed down by <Form> to the <InputEmail> component (as well as any other props), will be passed down to the <Input> component.
PS: The code inside registerInputs() that checks for child.props.children does not work as intended: at the time it is invoked, the <InputEmail> component does not have children. Like the name implies, it checks for children passed down as props. And the only prop passed was initialValue.
As minor issues I would suggest to make 2 more changes:
In registerInputs(), you directly modify props. This is generally not a good idea. Better is to make a copy of props, and add your form-methods to the copy. You can use React.Children.map to do this. See official docs here.
Instead of hard-coding the name="email" etc of your <Input> component, inside <InputEmail>, better is to put the default values of these in default values of props, using propTypes, as explained here in official docs.
I want to so some customization with checkbox, it can look like this:
so I wrap my custom checkbox into a React Component:
require('../../less/ck-checkbox.less');
var React = require('react');
var CkCheckbox = React.createClass({
propTypes: {
name: React.PropTypes.string,
text: React.PropTypes.string,
defaultChecked: React.PropTypes.bool,
onChange: React.PropTypes.func
},
getDefaultProps: function() {
return {
name: 'checkbox',
text: '',
defaultChecked: false,
onChange: function () {}
};
},
render: function() {
return (
<div className="ck-checkbox">
<label>
<input
type="checkbox"
name={this.props.name}
ref="c"
defaultChecked={this.props.defaultChecked}
onChange={this.props.onChange.bind(this, this.refs.c.checked)}
/>
<span className="icons">
<span className="icon-checked-o icon-true"></span>
<span className="icon-circle-o icon-false"></span>
</span>
{this.props.text.length > 0 ?
<span className="ck-checkbox-text">{this.props.text}</span> : null
}
</label>
</div>
);
}
});
module.exports = CkCheckbox;
and my container is like this:
var React = require('react');
var CkCheckbox = require('./CkCheckbox.js');
var Test = React.createClass({
render: function() {
return (
<div>
<CkCheckbox onChange={this._handleChange}/>
</div>
);
},
_handleChange: function(checked, e) {
console.log(checked)
}
});
module.exports = Test;
you can see that, I tried to bind this.refs.c.checked in the onChange callback, but it doesn't work.
so, how can I get the checked state of my custom checkbox in Test component in the _handleChange function?
In this case you don't need use refs because you can get checked property from e argument
// CkCheckbox component
<input type="checkbox"
name={this.props.name}
defaultChecked={this.props.defaultChecked}
onChange={ this.props.onChange } />
// Test component
_handleChange: function(e) {
var checked = e.target.checked;
console.log(checked)
}
Example
or if you want pass only checked property you can do it like this
// CkCheckbox component
handleChange: function (e) {
this.props.onChange(e.target.checked);
},
<input type="checkbox"
name={this.props.name}
defaultChecked={this.props.defaultChecked}
onChange={ this.handleChange } />
// in Test component
_handleChange: function(checked) {
console.log(checked)
}
Example
This is a simple example you can use to get the custom value or the value of your checked box, and also to check if the box is checked.
export default class SearchBoxContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
boxAll: false
};
}
handleChange = event => {
this.setState({ boxAll: event.target.checked }, () => {
console.log("This returned true or false", this.state.boxAll);
});
};
render() {
return (
<div className="search-container">
<SearchBox />
<div className="filter-country">
<h1>Filter</h1>
<div className="filter-country-container">
<div>
<input
type="checkbox"
id="checkBoxUS"
name="US"
value="US"
onChange={this.handleChange}
/>
<label htmlFor="US">All Jobs</label>
</div>
</div>
</div>
</div>
);
}
}
It is important to know that in this example, I used the "setState()" callback just for demonstration purposes, but you can pass the value to other components by props or wherever method you prefer. Also, when the checkbox is checked the value will return "true"
I'm trying to get familiar with how inheritance works between components in react.js and I'm having a bit trouble.
Requirements - Basically, what I want to achieve is for the value of my check box to change when I click on the button.
The check box is inheriting the value of 'checkedVal', which is set in state in the Heading.
I can get the correct value in the checkbox when it first loads but cannot change it when I click on the button. Any ideas would be appreciated?
var Heading = React.createClass({
propTypes: {
name: React.PropTypes.string,
age: React.PropTypes.number
},
getDefaultProps: function(){
return {
name: 'Keir',
age: 24,
}
},
getInitialState: function(){
return {
manU: false,
checkedVal: false
}
},
manUFan: function(){
this.setState(function(previousState, currentProps){
return {
manU: !previousState.manU,
checkedVal: !previousState.checkedVal
}
});
},
render: function(){
var msg;
if(this.state.manU){
msg = "I am a United fan."
} else {
msg = "I dream of being a united fan."
}
return (
<div>
<h1>Attempting React</h1>
<ul>
<li>{this.props.name}</li>
<li>{this.props.age}</li>
</ul>
<button onClick={this.manUFan}>Do You Support Man U?</button>
<CheckBox checkBoxVal={this.state.checkedVal}/>
<p>{msg}</p>
</div>
)
}
});
var CheckBox = React.createClass({
propTypes: {
checkBoxVal: React.PropTypes.bool
},
render: function(){
return (
<div>
<input type="checkbox" defaultChecked={this.props.checkBoxVal}/>
</div>
)
}
});
ReactDOM.render(<Heading />, document.getElementById('content'));
The defaultValue and defaultChecked props are only used during initial render. If you need to update the value in a subsequent render, you will need to use a controlled component. https://facebook.github.io/react/docs/forms.html#controlled-components
So in your case here's how you'd implement a controlled CheckBox.
var Heading = React.createClass({
...
getInitialState: function(){
return {
checkedVal: false
}
},
handleChange: function(event){
this.setState({checkedVal: event.target.value});
},
render: function(){
...
return (
<div>
...
<CheckBox onChange={this.handleChange} checkBoxVal={this.state.checkedVal}/>
...
</div>
);
}
});
var CheckBox = React.createClass({
propTypes: {
checkBoxVal: React.PropTypes.bool
},
render: function(){
return (
<div>
<input type="checkbox" onChange={this.props.onChange} value={this.props.checkBoxVal}/>
</div>
);
}
});