How to create a controlled Fabric UI TextField component? - reactjs

I've been trying to code a controlled TextField component in the standard way just like in React docs:
handleChange(event) {
this.setState({
text: event.target.value
});
}
<TextField label='Enter Text' value={this.state.text} onChange={this.handleChange}/>
The code above is what I've been using, but it seems that it doesn't change the state of the react component, because in the same form if I change a controlled checkbox, it resets the textfield to be empty. If I use a standard html input element it works just as expected and doesn't clear the field.
What am I doing wrong here? Shouldn't TextField work the same way as a text type input?

From the docs, onChange is not a property. Use onChanged instead. Note that the return value is the textfield's value, not an event.

According to this example:
handleChange(value) {
this.setState({
text: value
});
}

I do not know what you want to do
but ... If what you need is to pass the input value to a text label, you can do it this way:
First you must declare an interface outside of your class
interface myState {
value1: string;
}
you must include your Interface in the class.
class TextFieldControlledExample extends React.Component<{}, myState> {...}
I suppose that for TypeScript themes you must publicly declare the interface of which you are using.
public state: myState = { value1: ''};
you must declare a function within the render to assign the value of the state
public render() {
const { value1 } = this.state;
in this way you assign the value of your inputs. but to update it you have to create a function and call it on the onChange
<TextField
label="Enter Text"
value={this.state.value1}
onChange={this._onChange}
styles={{ fieldGroup: { width: 300 } }}
/>
<Text variant='xxLarge' nowrap block>
{value1}
</Text>
to assign the input value to the state you have declared using setState. must do a function.
private _onChange = (ev: React.FormEvent<HTMLInputElement>, newValue?: string) => {
this.setState({ value1: newValue || '' });
};
You can see the example working here
https://codepen.io/jasp402/pen/EBWBgO

Related

Set value of Reactstrap's Input to empty string

How do I set the value of a Reactstrap Input to be empty? I am using code like this.
handleChange = (event) => {
this.setState({message: event.target.value});
};
< Input onChange = {this.handleChange}/>
Also, what is the best practice for getting the value of an input: refs or onChange?
You gotta set a value property for your input which holds the value of your input, so your input looks like this:
<Input value={this.state.message} onChange={this.handleChange} />
and then when you want to clear its value, you just do this:
this.setState({message: ''})
and for your other question, the answer is that the Refs provide a way to access DOM nodes or React elements created in the render method, according to React documentation You can use Refs when:
Managing focus, text selection, or media playback.
Triggering imperative animations.
Integrating with third-party DOM libraries.
and you have to AVOID using refs for anything that can be done declaratively.
Then, here we just use onChange because we don't simply need Refs!
You need to assign state value to your input field.
public class myApp() extends React.Component {
constructor(props){
super(props);
this.state = {
message: ''
};
}
handleChange = (event) => {
this.setState({message: event.target.value});
};
render() {
return (
<Input value={this.state.message} onChange={this.handleChange} />
);
}
}

Setting the defultValue of TextField component of Material UI in React

I am developing a React JS application. What I am doing now is I am fetching data asynchronously from the server and render the values in the TextField. I know how to do it and my approach is working as well. But, I just do not like my current approach.
This is the working approach
class TestComponent extends React.Component {
constructor(props)
{
super(props);
this.fetchName = this.fetchName.bind(this);
this.handleChange = this.handleChange.bind(this);
this.state = {
name : ''
}
}
fetchName()
{
//get the name asynchronously from the server. I am using Axios
this.setState({ name : nameValueFromTheServer })
}
handleChange(e)
{
this.setState({ name : e.target.value })
}
render()
{
return (
<MuiThemeProvider>
<div>
<TextField onChange={this.handleChange} label="Name" value={this.state.name} />
</div>
</MuiThemeProvider>
)
}
}
The thing I do not like about above approach is that I have to implement handleChange method to retrieve the value of the input value. If I do not implement it, I cannot change the name input value because the state value is not changed. To retrieve a simple input value, I have to write extra lines of code. In jQuery, I just retrieve the input value like this, $(selector).val(). Without implementing the handleChange method, I can use the ref like this.
<TextField inputRedf={(input) => this.tfName = input } label="Name" />
Then I retrieve the value dynamically like this.
this.tfName.value
The problem with using the reference is setting the default value which is fetched asynchronously from the server.
I can set the default value like this to the TextField
<TextField inputRedf={(input) => this.tfName = input } defaultValue={this.state.name} label="Name" />
Pay attention to the defaultValue attribute in the above code. When I set the value using defaultValue, the initial value of the name state will be set to the text field. But we can still change the input value of the name typing in from the UI even if we do not implement the handleChange event. But the problem is that I am getting the data asynchronously and setting the this.state.name dynamically.
So in the component constructor, the name state is empty. Then I set it in the callback of the asynchronous call. But the defaultValue can be set only once. So the input field is always showing empty. What I like to know is, how can I set the defaultValue of the TextField dynamically? The reason I am using ref is that I do not want to implement the onChange event as well to track state the reset the input value. If I could set the defaultValue dynamically, I will just the value dynamically in the callback of the asynchronous call. What is the best solution to simplify this scenario?
You don't need default value actually. If you want to avoid using onChange handler you can imperatively set input value in async callback:
class TestComponent extends React.Component {
constructor(props) {
super(props);
this.fetchName = this.fetchName.bind(this);
this.handleChange = this.handleChange.bind(this);
}
fetchName() {
if(this.tfName.value == '') {
// only update if user have not changed the input value.
this.tfName.value = nameValueFromTheServer;
}
}
render() {
return (
<MuiThemeProvider>
<div>
<TextField
inputRef={(input) => this.tfName = input }
label="Name"/>
</div>
</MuiThemeProvider>
);
}
}

Add Name to Array using setState gives error

Im trying to add an item to an array in my state. However, i get the following error:
Objects are not valid as a React child (found: object with keys...)
My github url to the codes, Please help.
class Tutorial2Screen extends Component {
constructor(props) {
super(props);
this.state = {
num: 0,
name: "",
arr: ["John", "Mary", "Steve"]
};
}
addNameToArr(newName) {
this.setState(prevState => ({
arr: prevState.arr.concat(newName)
}));
}
Input & Button codes:
<Input
placeholder="Name"
onChangeText={name => this.setState({ name })}
value={this.state.name}
/>
</Item>
<Button
block
style={{ margin: 10 }}
onPress={this.addNameToArr.bind(this)}
>
you have binded "addNameToArr" method with Button on press event, and in "addNameToArr" method, first argument you are expecting a "newName" (input field value) value to be passed in. But, as method is bind with an event call, so you are not getting text input value as argument.
Use:
addNameToArr() {
this.setState(prevState => ({
arr: prevState.arr.concat(prevState.name)
}));
You have to do it like this :
this.setState({
arr:this.state.arr.concat(this.state.name);
})
or you can use it like this by es6 spread syntax :
this.setState({
arr:[...this.state.arr,this.state.name];
})
changed newName to this.state.name because you are changing this.state.name with onchange handler not newName
thanks for all your help! your inputs have helped me find the solution to my question. I have altered my jsx code by adding in brackets and passing the argument directly to the arrow function and it worked! github contains the code that works.

React : State and props on the same parameter

I'm a junior developer.
I use Textfield of material ui, but i have a problem. I get the value by a property, and it works ! however i can't edit the textfield, so i would want to use the onChange parameter, this is my code :
<TextField ref="docLibelle" value={this.props.lastuploadfile.content} onChange={this._handleTextFieldChange}
And my function :
_handleTextFieldChange = (e:any) => {
this.setState({
showReferenceIsRequired : false,
libelDoc: e.target.value
});
}
And I try that :
<TextField ref="docLibelle" value={this.state.libelDoc&& this.props.lastuploadfile.content} onChange={this._handleTextFieldChange}
But it doesn't work .. How can i get the value by the property and edit also the textfield ?
Thank you for yours answers !
I think the solution is pretty simple. Since you want to be able to change the textField value and also initialize it with a value you can just setState with props in your componentDidMount method
componentDidMount(){
this.setState({libelDoc: this.props.lastuploadfile.content})
}
and use it like'
<TextField ref="docLibelle" value={this.state.libelDoc} onChange={this._handleTextFieldChange}
Issue is, in value property you are using the props value and inside the onChange method updating the state value, because of that your textfield is read only.
Solutions:
1. Pass a function from parent component and onChange of textfield use that function to update the parent value, it will work, like this:
In Child component:
<TextField ref="docLibelle" value={this.props.lastuploadfile.content} onChange={this._handleTextFieldChange}/>
_handleTextFieldChange = (e:any) => {
this.setState({
showReferenceIsRequired : false,
});
this.props.updateValue(e.target.value);
}
In Parent component:
updateValue(value){
let = this.state.lastuploadfile;
lastuploadfile.content = value;
this.setState({lastuploadfile})
}
2. Store the props value in state variable and use that variable in value property of textfield.
Store the initial value of textfield in state variable:
constructor(props){
super(props);
this.state = {libelDoc: props.lastuploadfile.content}
}
Use that variable in value property in textfield:
<TextField ref="docLibelle" value={this.state.libelDoc} onChange={this._handleTextFieldChange}
Update that state variable in onChange method:
_handleTextFieldChange = (event, value) => {
this.setState({
showReferenceIsRequired : false,
libelDoc: value
});
}

How come I can't type anything into my React search box?

I have a component called SearchInput and it has in it
<input
type='text'
className='input-field'
value={value}
placeholder={this.state.placeholder}
// onFocus={::this.onFocus}
// onBlur={::this.onBlur}
// onKeyUp={::this.onKeyUp}
// onKeyDown={::this.hanleArrowKeys}
// onChange={::this.onChange}
/>
However, when I type anything into it, nothing happens. The text doesn't even appear. What am I doing wrong?
Probably your state is not updating, maybe didn't you bind "this" to function onChange?
Here is an example of correct input in react:
class SearchInput extends Component {
constructor(props) {
super(props);
this.state = { value: '' };
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
this.setState({ value: event.target.value });
}
render() {
return <input type="text" value={this.state.value} onChange={this.handleInputChange}/>;
}
}
Probably you are binding the value of the input box with an attribute in the state of the component and you are either not providing an onChange prop to the input tag or your onChange callback method is not updating the attribute in the state to which the input tag's value is bound.

Resources