Reputation: 12034
I created a basic input
, with few effects, but a simple input [type='text']
in the base.
But, I'm not able to get the value
or any property of the state
from my Input
control.
How can I expose a property from my Input
control to any other Component
?
input.js
import React from "react";
class Input extends React.Component {
constructor(props) {
super();
this.state = {
inputValue: "",
fieldActive: false,
label: props.label,
placeholder: props.placeholder,
type: props.type,
maxLength: props.maxLength,
error: false,
required: props.required
};
this.updateInputValue = this.updateInputValue.bind(this);
this.activateField = this.activateField.bind(this);
this.disableFocus = this.disableFocus.bind(this);
}
activateField() {
this.setState({
fieldActive: true
});
}
disableFocus(e) {
if (e.target.value == "") {
this.setState({
fieldActive: false
});
this.setState({
error: this.state.required
});
} else {
if (this.state.type == "email") {
this.setState({
error: !/^[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[A-Za-z]+$/.test(e.target.value)
});
}
}
}
updateInputValue(e) {
this.setState({
inputValue: e.target.value
});
this.activateField(e);
e.preventDefault();
}
render() {
return (
<div className="form-group field-group">
<label
htmlFor=""
className={
this.state.fieldActive
? this.state.error
? "field-active form-label floating error"
: "field-active form-label floating"
: "form-label floating hide"
}
>
{this.props.label}
</label>
<input
className={
this.state.error
? "form-input floating-label error"
: "form-input floating-label"
}
type={this.props.type}
placeholder={this.props.placeholder}
maxLength={this.props.maxLength}
value={this.state.inputValue}
name={this.props.id}
id={this.props.id}
autoComplete="off"
onFocus={this.activateField}
onBlur={this.disableFocus}
onChange={this.updateInputValue}
/>
</div>
);
}
}
export default Input;
MyView.js
<Input
label="Firstname"
placeholder="Firstname"
id="firstname"
type="text"
required='true'
value=''
maxLength='20'
onChange={this.handleChange}
/>
</div>
Upvotes: 1
Views: 1913
Reputation: 2283
You can only do that to its parent or child components. For others, you wouldn't be able to do it.
For parent components, like MyView, check this question: How to pass data from child component to its parent in ReactJS? which has mostly easy-to-understand solutions.
Or, you can check other answers.
For parent to child, easy. Just plug in input = {this.state.x}
where x is the property you want to expose and then you can access that by using this.props.input
.
Upvotes: 1
Reputation: 12034
I found a way, not sure if it is better, but it is working.
Basically, you can pass a function a receive it as props
in the component constructor.
And use the view function in the component as a callback function.
view.js
<Input
label="Firstname"
placeholder="Firstname"
id="firstname"
type="text"
required='true'
value=''
maxLength='20'
onChange={this.handleChange}
/>
handleChange = (id, value) => {
console.log(id);
console.log(value);
console.log('-');
/*this.setState({
[e.target.name]: e.target.value
});*/
};
Input.js
class Input extends React.Component {
constructor(props) {
super();
this.state = {
inputValue: "",
fieldActive: false,
label: props.label,
placeholder: props.placeholder,
type: props.type,
maxLength: props.maxLength,
error: false,
required: props.required,
inputChange: props.onChange,
id: props.id
};
console.log(props);
this.updateInputValue = this.updateInputValue.bind(this);
this.activateField = this.activateField.bind(this);
this.disableFocus = this.disableFocus.bind(this);
}
activateField() {
this.setState({
fieldActive: true
});
}
disableFocus(e) {
if (e.target.value == "") {
this.setState({
fieldActive: false
});
this.setState({
error: this.state.required
});
} else {
if (this.state.type == "email") {
this.setState({
error: !/^[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[A-Za-z]+$/.test(e.target.value)
});
}
}
}
updateInputValue(e) {
this.setState({
inputValue: e.target.value
});
if(this.state.inputChange!= undefined && this.state.inputChange != null)
this.state.inputChange(e.target.id, e.target.value)
this.activateField(e);
e.preventDefault();
}
render() {
return (
<div className="form-group field-group">
<label
htmlFor=""
className={
this.state.fieldActive
? this.state.error
? "field-active form-label floating error"
: "field-active form-label floating"
: "form-label floating hide"
}
>
{this.props.label}
</label>
<input
className={
this.state.error
? "form-input floating-label error"
: "form-input floating-label"
}
type={this.props.type}
placeholder={this.props.placeholder}
maxLength={this.props.maxLength}
value={this.state.inputValue}
name={this.props.id}
id={this.props.id}
autoComplete="off"
onFocus={this.activateField}
onBlur={this.disableFocus}
onChange={this.updateInputValue}
/>
</div>
);
}
}
export default Input;
Upvotes: 0
Reputation: 31
You can only pass its value to parent or child components. So if you want to share some state of a component X with a component Y, then Y should be either X's ancestor or a child of X or a child of X's ancestor.
Parent component can get child's value either from ref
or from a callback:
ref='myinput'
to Input
, then access it by this.refs.myinput.value
from parent component.grabChildValue
function to a parent method, then add this.props.grabChildValue(this.value)
call to input's onChange
.Upvotes: 1