REACT ADMIN | TEXTINPUT CHANGE VALUE - reactjs

how can I change the value of an TextInput in react-admin.
My idea was
<TextInput label="..." source="..." value="MY VALUE" />
But that doesn't work.
pls help.

You can't do this with the react-admin's TextInput as it is a connected field to the backing react-final-form form and hence you don't control the input.
You should state what is your final aim. I can think of two options:
If you want to have a controlled input you can simply use material-ui's TextField and pass to it your custom value as well as handle the onChange event.
If you don't want to control the value by yourself but alter it in the form state under some condition, you can then use the hook provided by react-final-form:
const form = useForm();
form.change("myValue", newValue);
...
<TextInput label="My Value" source="myValue" />

Since react-adminv4.0.0 library no longer uses react-final-form instead it uses react-hook-form. So you would need to change your relevant code to use it as well.
import {useFormContext} from "react-hook-form";
...
const {setValue} = useFormContext();
setValue("myValue", newValue);

If the value of your input is null or undefined you can use the initialValue prop to set the value when the page loads.
<TextInput source="mySource" initialValue="MY VALUE" />
See React-Admin Input Docs: https://marmelab.com/react-admin/Inputs.html#common-input-props
If you are looking to dynamically change the value after the page has loaded, I would recommend following Kia's answer to leverage the useForm hook.

Related

Conditionally enabling a form button with react-hook-form and material ui

I'm creating a React form with Material UI. My goal is to force the user to answer all the questions before they can click the download button. In other words I'm trying to leave the download button in the disabled state until I can determine that values are set on each field. I've tried to get this working with and without react-hook-form.
What I've tried
Without react-hook-form...
I have my example in coding sandbox here:
https://codesandbox.io/s/enable-download-button-xwois4?file=/src/App.js
In this attempt I abandoned react-hook-form and added some logic that executes onChange. It looks through each of the formValues and ensures none of them are empty or set to "no answer". Like this:
const handleInputChange = (e) => {
// do setFormValues stuff first
// check that every question has been answered and enable / disable the download button
let disableDownload = false;
Object.values(formValues).forEach((val) => {
if (
typeof val === "undefined" ||
val === null ||
val === "no answer" ||
val === ""
) {
disableDownload = true;
}
});
setBtnDisabled(disableDownload);
The problem with this approach, as you'll see from playing with the UI in codesandbox, is that it requires an extra toggle of the form field value in order to detect that every field has been set. After the extra "toggle" the button does indeed re-enable. Maybe I could change this to onBlur but overall I feel like this approach isn't the right way to do it.
Using react-hook-form
With this approach...the approach I prefer to get working but really struggled with, I ran into several problems.
First the setup:
I removed the logic for setBtnDisabled() in the handleInputChange function.
I tried following the example on the react-hook-form website for material ui but in that example they're explicitly defining the defaultValues in useForm where-as mine come from useEffect. I want my initial values to come from my questionsObject so I don't think I want to get rid of useEffect.
I couldn't figure out what to do with {...field} as in the linked material ui example. I tried dropping it on RadioGroup
<Controller
name="RadioGroup"
control={control}
rules={{ required: true }}
render={({ field }) => (
<RadioGroup
questiontype={question.type}
name={questionId}
value={formValues[questionId]}
onChange={handleInputChange}
row
{...field}
>
but I get an MUI error of : MUI: A component is changing the uncontrolled value state of RadioGroup to be controlled.
Also, I don't see that useForm's state is changing at all. For example, I was hoping the list of touchedfields would increase as I clicked radio buttons but it isn't. I read that I should pass formState into useEffect() like this:
useEffect(() => {
const outputObj = {};
Object.keys(questionsObject).map(
(question) => (outputObj[question] = questionsObject[question].value)
);
setFormValues(outputObj);
}, [formState]);
but that makes me question what I need to do with formValues. Wondering if formState is supposed to replace useState for this.

React-Hook-Form setValue for Material-UI Autocomplete doesn't work

I'm building a form with React-Hook-Form and Material-UI. Each Material-UI form component is wrapped into a react-hook-form Controller component.
The user has the option to populate the form automatically with different sets of pre-defined values when clicks on a button. I'm trying to use setValue() to achieve that and it seems to work fine for text input and select. However, for autocomplete the new value is not rendered although when submitting the form it is correctly sent. Also, when a text area is rendered the content seems to be mixed with the label.
Here is a complete example:
CodeSandbox Link
You need to cotroll the value of AutoComplete by passing value attribute to AutoComplete component, But since you are using string value you couldn't pass value to AutoComplete directly and you should to find the target option like this:
<Autocomplete
...
value={typeof value === 'string' ? options.find(o => o.name === value) : (value || null)}
/>
Your textarea problem occurs because your value by default is undefined and material considers the textare as uncotrolled input, to solve it you can pass empty string when value is undefined, like this:
<TextField
...
value={value || ''}
...
/>

How can i make a placeHolder visible while making my Datepicker component controlled( value = dateOfBirth)

I was implementing a Datepicker in antd but i wanted the input bar to show me the placeholder but instead it shows me the initial state value here is the code
<DatePicker
value={dateOfBirth}
placeholder="Date of Birth"
format={dateFormat}
onChange={(date) => setDateOfBirth(date)} />
Now i wanted the placeholder to be visible at the same time i want the datepicker component to be a controlled componenent.But i couldn't make the placeholder visible unless i remove value={dateOfBirth} as a result which makes my component uncontrolled component. so is there any way to achieve both properties at the same time.
Since you're passing a moment object as the default value, the date picker component will use that as its initial value and that's why it's not displaying the placeholder, since placeholders are only used when there is no value. You need to set the initial state value to null.
const [dateOfBirth, setDateOfBirth ] = useState(null);
Do this, it worked for me well
Set the initial state value to null
const [dateOfBirth, setDateOfBirth ] = useState(null);
then replace
placeholder="Date of Birth" with placeholderText={"Date of Birth"}

how to get selected value onChange of react redux-form drop down

I am using react redux form Fields and I have drop down of classes. I am able to select any class from drop down.
but the issue is that whenever I select any value (class) from drop down I want to trigger action onChange. When I trigger action with on change drop down values does not set and it does not show selected value.
I am using following lines of code
<Field name="class._id" component="select" className="form-control" onChange={this.onChange.bind(this)} >
<option value="">Select class...</option>
{this.props.classes.map(Class =>
<option value={Class._id} key={Class._id} >{Class.name}</option>)}
</Field>
here is onChange function
onChange(){
console.log(" Triggered")
}
If I do not set onChange event my drop down works correctly and it shows selected value correctly with proper text.
but I want to call function whenever use select any value
Can you give more context for this code, perhaps putting the whole component (and any modules or containers or whatever) in a JSBin or Fiddle? That will help SO posters better know how to help you. That said, it looks like your code is correct. You can get the value out of the select kind of like this:
onChange(event) {
console.log(event.target.value);
}
Does that help?
May be you should better use fields prop of redux and standard html elements?
const {fields} = this.props
<select {...fields.class} onChange={this.handleChange}>
...
handleChange(event) {
// do your stuff
this.props.fields.class.onChange(event)
}

How to clear the text field in formsy material ui React

Hi I am using React 14 and writing it in ES6. I am using formsy-material-ui for form validations. There is a scenario where I want to clear the value of text field on click of a button.
I tried the following code
<FormsyText
name="email"
ref="email"
validations="isEmail"
validationError="Invalid Email"
hintText="Email"
value={this.state.emailValue}
/>
And on click of the button, I am executing the following line of code
this.setState({emailValue : ''});
But the text field is not getting cleared.
How to clear it.
Pls help.
So, if you were using a controlled input (maybe using directly the TextField from Material-ui) - your code would be right, however the FormsyText component handle it's value internally.
If you pass a value or defaultValue it'll just be used when it's rendered, you can check it here.
I only see one way to clear the value now, in an imperative style.
this.refs.email.setState({ value: "" })
Note: I suggest you to change the way you're using the ref. Using refs with a string is deprecated and probably will be removed in the future. Instead you should pass a function that's gonna receive that component. https://facebook.github.io/react/docs/more-about-refs.html
Example:
<FormsyText
name="email"
ref={(node) => this._emailText = node}
validations="isEmail"
validationError="Invalid Email"
hintText="Email"
value={this.state.emailValue}
/>
//And to clear it
this._emailText.setState({ value: "" })
Try reset field after setState:
this.setState({emailValue : ''});
this.refs.email.reset()
Also you can reset all form.
this.refs.form.reset()
const formRefdeposit = useRef(null);
<Formsy
onValidSubmit={handleSubmit}
onValid={enableButton}
onInvalid={disableButton}
ref={formRef}
>
....Form Fields
</Formsy>
if you have class in your js file then use
this.formRef.current.reset();
if without class then use
formRef.current.reset();

Resources