I have a form which loads with default values.
I want a button to reset all form's values to empty values.
The built in handleReset function only resets the values to the default values that the form was loaded with.
I tried to change the props with default values with concept similar to the code below, but the props are "read only".
resetToEmpty(){
this.props.user = {};
}
<button type="button" onClick={ resetToEmpty}>Clear form demo data</button>
Code sand box https://x7069jq8lz.codesandbox.io/
How could reset all formIk fields to empty values?
Thanks!
The code sand box is broken, but i think you should consider to change your props to empty in state above, and just add 'enableReinitializing' prop to your Formik instance.
Then after getting new props your initialValues in Formik should be updated.
You have to pass an empty user to your form component again. So you'll have to bubble up the reset event, that is, send it to form's parent component where you initially passed the user object.
Let's say that when you click the Reset button you'll have to do this where you're setting the user initially. As it's being passed as a prop to formik this should go in your parent component. Something like this:
user: { name: '', age: '', gender: null }
Related
I am trying to update my state in ReactJS. To do this I have an input field in a Reactjs class. The field is automatically filled in with data from a parent class. The field looks like this:
<input
onChange={e => this.props.store.addLego(e)}
name="piece"
value={this.props.row.original.piece}
/>
The addLego function is designed to update my state and is in a MobX store. It looks like this:
addLego = action("addLego", e => {
this[e.target.name] = e.target.value;
});
However, I can't actually edit the input field! Nothing changes in the field when I type! Thanks for your help!
If you set a value attribute to an <input> field that field becomes a controlled input. This means that whatever gets passed to value is rendered on the screen. In your case, if you are not updating this.props.row.original.piece the <input> field will never get a new value. I'll suggest to read this bit of React's documentation https://reactjs.org/docs/forms.html#controlled-components
It is basically suggesting to keep the new value somewhere (in the component's state for example) and set it back as a value to the field.
Follow this tutorial here will solve your problem. It's a good read too for handling single or multiple inputs
Basically, you'll need a state in the constructor
this.state = {value: ''};
Event handler to set the value every onchange
handleChange(event) {
this.setState({value: event.target.value});
}
And the setup for input
<input type="text" value={this.state.value} onChange={this.handleChange} />
I'm using Redux Form v.7.1.2 and am trying to have the submit button disabled initially. When the user activates the change or keyup events, I want the form to check if ANY of the form fields within the form have any value. If so, I want the submit button to become enabled. I don't have any fields required. I just need to make sure that at least one of them has a value filled in.
I have achieved this in jQuery:
// Change disabled attribute on search box submit button depending on if there is a value in any field
$searchFormFields.on('change keyup', function() {
$('#search-box-search-btn').prop('disabled', true);
$searchFormFields.each(function() {
if ($(this).val().length > 0) {
$('#search-box-search-btn').prop('disabled', false);
return false; // break the loop
}
});
});
I am converting the site to use React and Redux now though, and I have absolutely no idea where to begin trying to get this to work. Any ideas?
If you just want to check that no fields have been filled out, you can use the following line:
<button type="submit" disabled={this.props.pristine}>Submit</button>
pristine is a prop that redux-form adds that you can reference if the form has not had any fields filled out. You can check out more in their API Docs. It is comparing the current form values to the initial values on the form.
It turns out I actually needed to disable the button if the form had not been changed since the last submit.
In order to check for that condition, you can assign the current values as the initial values when submitting the form. Then when determing if a form is pristine, redux-form will compare any current values to the last initial values that were set on the latest submit.
import { Field, reduxForm } from 'redux-form';
class SearchFilters extends Component {
constructor(props) {
super(props);
this.onSubmit = this.onSubmit.bind(this);
}
onSubmit(values) {
// Check if the form values have changed since the last submit
// The dirty boolean (signifies if the form has changed from its initial values) is established by redux-form by comparing the currently entered values to the initial form values
// After we identify the form as having been changed, we will send the new form values to replace the original initial form values so redux-form is always comparing the current form values against the last submitted form values
if (this.props.dirty) {
// Set the initial values for the form on the redux store (This is used by redux form to compare the current values to the initial values so we can determine if there are new values since the last submit)
this.props.initialize(values);
}
}
renderField(field) {
return (
<div className="search-parameter">
<input type="text" {...field.input} />
</div>
);
}
render() {
const { handleSubmit, submitting, invalid } = this.props;
return (
<form onSubmit={handleSubmit(this.onSubmit)} >
<Field
component={this.renderField}
key="keyword"
name="keyword"
/>
<Field
component={this.renderField}
key="type"
name="type"
/>
<button
type="submit"
disabled={submitting || pristine || invalid}
>
Search
</button>
</form>
);
}
}
export default reduxForm({
validate,
form: 'SearchFiltersForm',
})(connect(mapStateToProps, null)(SearchFilters));
I actually have 2 combobox (react-widgets) on my reduxform.
My first combobox works perfectly because I fetch my datas onChange.
But when I focus the second one I want my data loaded in it depending on the value of the first one.
The problem is : I have data in the render when I console.log it but the component not rerendering. I have to type something in the field to see my data, it's like only the onchange trigger the rerendering.
Field in the form:
<Field
component={HouseComp}
name="house"
currenthouses={currenthousesValue}
onFocus={getHouses(props)}
{...props}
/>
My component render:
<Combobox id="house"
data={currenthouses}
{...input}
/>
the getHouses function is a fetch returning something like :
props.dispatch(change('form', 'currenthouses',data))
the currenthousesValue is from a selector:
const currenthousesValue = selector(state, 'currenthouses');
I tried to force the update by using componentDidUpdate but even if I see the call of my render function the UI is not refreshing.
I also tried to load the data on "onBlur" from the first one but same result.
I am new to React. But I faced a similar issue in React. In your case when the value of first combo box changes, The value of data attribute of second form also changes. But your second combobox is not re-rendering may be becuase it is not subscribed to componentWillReceiveProps event.
Something like this(taken from my code):
componentWillReceiveProps(nextProps) {
this.setState({
groups: nextProps.groups,
invoices_count: nextProps.groups.length
});
}
I have a modal with some input fields. I can easily pass the data automatically with the user typing an input, using onChange function in the input field, as
<Input onChange={this.props.store.handleCategoryChange} type="text" />
and .. (Using a mobx store, irellevant though)
#observable categoryValue;
#action handleCategoryChange = (e, data) => {
this.categoryValue = data.value;
e.preventDefault();
};
However, I want to add a function where the user can pre-fill this with information elsewhere in the application. I have the data to pre-fill the input fields with, but I can't figure out how do actually input it programatically, without the user doing it?
I need to invoke the above handleCategoryChange function. But my variable would be equal to data.value .. Which presents a problem! Invoking this function by myself isn't possible, because I won't have the event e nor a value called data.value as I will "just" pass in a variable by itself.
What's the right way to programatically fill an input field automatically in React, using variables elsewhere? I need to invoke the onChange function somehow, but the input values will be different..
Use controlled component for this situation, define a value property of input element like this:
<Input value={variable_name} ....
Whenever you will update that variable, automatically that value will get populated in input element.
Now you can populate some default value by assigning a value to variable_name and user can update that value by onChange function.
As per DOC:
An input form element whose value is controlled by React in this way
is called a "controlled component".
Pass in the value property for input:
<input type="text" value={this.state.value} onChange={(e) => {this.setState({value: e.target.value })}/>
you can use the controlled component and pass the value to it.
<input type="text" value{this.state.value}
onChange={()=> {this.setState({value:e.target.value })}}
Good question. I'm having the same issue, and just found a solution.
The problem is that:
You can't just use the default state of the modal component to set the initial input value, because the modal renders one time within the parent component (starting off invisible), so the default state of the Modal wont keep up with any changes to the 'pre-filled' info in the store that the inputs within the modal require access to.
You can't use the value attribute of the input to reference some redux store prop, since this is needed to reference the onChange function so the user can make changes to that pre-filled info.
And, you can't use the onChange function to set the initial value, because it is required to update the local state with the users changes - not set an initial value. Anyway, this requires the user to click on something, and you want the modal inputs to be pre-populated before the user does anything as soon as the modal opens...
So. What we need is to update these input fields every time the Modal attribute isModalOpen (or whatever you are using) changes.
(ie, pre-populate the fields when the Modal is opened).
Again, note that opening the Modal is not RENDERING the modal, it was already rendered, once, and has sat there being invisible until that isModalOpen attribute changed to true.
The Solution:
Step 1: make a handler function in the Modal component that prefills the inputdata by updating the local state of the Modal component. Mine looks like this :
handlePreFillModalInputsOnOpen = () => {
this.setState(() => ({
orthForm: this.props.matchLexUnit['orthForm'],
orthVar: this.props.matchLexUnit['orthVar'],
oldOrthForm: this.props.matchLexUnit['oldOrthForm'],
oldOrthVar: this.props.matchLexUnit['oldOrthVar'],
source: this.props.matchLexUnit['source'],
namedEntityCheck: this.props.matchLexUnit['namedEntityCheck'],
styleMarkingCheck: this.props.matchLexUnit['styleMarkingCheck'],
artificialCheck: this.props.matchLexUnit['artificialCheck'],
error: ''
}));
};
Step 2: Make that function fire ONLY when the isOpen attribute of the modal changes from false to true.
(This is the meat of your problem I think).
Use the lifecycle method componentDidUpdate. This will execute every time the props of the modal change.
componentDidUpdate(prevProps) {
if (this.props.isModalOpen === true && prevProps.isModalOpen === false) {
this.handlePreFillModalInputsOnOpen();
}
}
Watch out
make sure that you have a conditional in componentDidUpdate, otherwise you can run into infinite-loop/performance issues
if you have the possibility of null values icoming in as the prefilled input info, make a null-check so that they will not be passed into the local state.
Hope this helps :)
How to Programmatically Prefill, Fill or Update input fields value in React or useState Hooks?
Firstly - Get and define the data from database
const **yourData** = isDataFromDatabase;
or if the data is stored in Redux, then...
const **yourData** = useSelector(isDataFromDatabase);
Secondly - append it as the default value of a useState hook
const [isDataValue, setIsDataValue] = useState(**yourData**);
Thirdly - create a function to watch and Update the changes made by the user to your data value and set it to the useState hook created above
/** handles Your Data Value */
const handleDataValue = (text) => {
setIsDataValue(text);
};
Lastly - in your input tag, use the useState State as the "Value" parameter so it can be updated with the onChange function
<input
className="css"
id="myDataInput"
type="text"
value={isDataValue}
placeholder={isDataValue}
onChange={(e) => handleDataValue(e.target.value)}
/>
Now when you load the component, the prefilled value will be shown and can be updated in the HTML Input field.
That's All.
I have a Semantic-UI modal that contains a redux-form as it's content. When opening the modal, I pass the form to it's content prop. The form element has an initialValues prop set to a prop mapped to state.
<FormModal
handleSubmit={ this.sortSubmit }
size='small'
formName='sortForm'
header='Sort'
headerIcon='sort'
content={
<SortForm table={ this.props.table } initialValues={ { orderBy: this.props.search.orderBy, orderDirection: this.props.search.orderDirection } } />
}
trigger={
<Button icon floated='right' size="mini">
<Icon name='sort' />
</Button>
}
/>
I then change this.props.search.orderBy by changing the redux state. Everything in the app updates to reflect the change, except this redux-form's initialValues, which should change when the state changes. I open the modal again, and the fields are reset to the old initialValues instead of the newly set values.
Any ideas why this would happen?
On a possibly related note, re-rendering the modal JSX does not seem to close the modal. Since the modal's initial state is closed, I would have assumed a re-render of it would re-close it.
You need to pass enableReinitialize={true} to your form.
Because enableReinitialize defaults to false. In this case, initialValues is only applied at componentWillMount.
Here is the part of doc about enableReinitialize:
When set to true, the form will reinitialize every time the
initialValues prop changes. Defaults to false. If the
keepDirtyOnReinitialize option is also set, the form will retain the
value of dirty fields when reinitializing.
For more info, please read reduxForm