Mutator to covert text to uppercase - reactjs

I tried different ways to implement mutator to convert text to uppercase as soon as user input text in the text field. But was not yet successful. The example provided by Erick seems correct, but maybe I am missing something.
/** Converts a form value to uppercase **/
const upper = ([name], state, { changeValue }) => {
changeValue(state, name, (value) => value.toUpperCase())
}
<Form
onSubmit={onSubmit}
mutators={{
...arrayMutators,
upper
}}
render={({
handleSubmit,
mutators: { push, pop, upper }, // injected from final-form-arrays above
pristine,
reset,
submitting,
values
}) => {
return (
<form onSubmit={handleSubmit}>
<div>
<label>Company</label>
<Field name="company" component="input" onChange={(e) => upper('company')} />
</div>
</form>
)}
}
/>
It's throwing an error when calling toUpperCase on value as value is coming undefined there. Really appreciate any help!
Update: 27-Oct-2018
I have realized we can use parser too, to solve this problem:
upper = value => {
return value ? value.toUpperCase() : ''
}
<Field name="company" component="input" parse={this.upper} />
Still looking for how mutator works and what's the error in my code.
Already Tried:
Mutate state based on existing fields
How to set/change Field value from external user action 🏁 React Final Form

As I know about react-final-form you can get this data directly
I will suggest, you can use this code
onChange={(event, value) => input.onChange(value.toUpperCase())}
https://codesandbox.io/s/0x9y71nwyp

Related

How can I collect data by sending the register as props to the child component using React Hook Form?

Using React Hook Form, when I want to collect data by sending register as props to child component to take input value from child component, it shows 'register is not a function' error.
How can I solve this?
const { register, formState: { errors }, handleSubmit } = useForm();
const onSubmit = (data) => console.log(data);
<form onSubmit={handleSubmit(onSubmit)}>
<fieldset>
<legend className='text-[#666666]' >Status</legend>
{
statusData.map(status => <CheckboxFilter register={register} key={status._id} status={status}/>)
}
</fieldset>
</form>
here child
//CheckboxFilter component
const CheckboxFilter = ({ status, register }) => {
return (
<>
<p className='text-[#858585] mt-2 text-[14px]' >
<label htmlFor={status?.name} className='cursor-pointer' >
<input {...register("checkBoxData")} type="checkbox" name="status" id={status?.name} value={"status?.name"} /> {status?.name}
</label>
</p>
</>
);
};
I created a sandbox here codesandbox and it works perfectly.
I took your code and only changed the CheckboxFilter component:
Removed the name property (register function returns the name of the input based in the string you pass to it as a parameter, you should not override it)
Removed the value property (that was making the value of the checkbox constant, because there wasn't onChange handler that was modifying it)
Changed ...register("checkBoxData") to ...register(checkBoxData${name}) so this way you can have every checkbox value individually in the form.
Anyway, if you want to have a different behaviour than what I have assumed, let me know and I will help.
-Ado

React final form - Unable to pass function to oChange prop

I have a in a form using react final form. I'm trying to pass the value of the current input to a function thats used when the field value changes. However when I type, it's taking no input.
<Field name="myField">
{({ input, meta }) => (
<div>
<TextField
type="text"
name={input.name}
value={input.value}
onChange={() =>
handleChange(input.value)
}
label="Title"
/>
</div>
)}
</Field>
I have a function handleChange above the render method. All I want to do is console the current value, and use a setState hook to update a state variable.
function handleChange(item: string) {
setTitle(item);
console.log(item);
}
What am I doing wrong?
I would personally use a useEffect to achieve this, but the issue is that once you add your own useEffect onto it, then it overrides the default action which saves the form value to the form itself.
So first you still have to do the default onChange. And you want to take the value from the input field using e.target.value.
In your example, you are passing the value of the input field into your handeChange, but becuase you arent saving the value back into the input and the form, its always going to be empty.
<Field name="myField">
{({input}) => (
<div>
<TextField
name={input.name}
value={input.value}
onChange={(e, val) => {
console.log(e.target.value);
handleChange(e.target.value)
input.onChange(e.target.value);
}}
/>
</div>
)}
</Field>

React-final-form - input losing focus after every keystroke

import React from "react";
import { Field, Form } from "react-final-form";
export function LogInDialog(props: { open: boolean; onClose: () => void }) {
const onSubmit = vals => {
alert(JSON.stringify(vals));
};
console.log("logindialog");
return (
<Form
key="unique_key_0"
onSubmit={onSubmit}
render={({ handleSubmit, form, submitting, pristine, values }) => (
<form onSubmit={handleSubmit} key="unique_key_1" id="unique_id_1">
<Field
key="unique_key_2"
id="unique_id_2"
name="email"
component={({ input: { onChange, value }, label }) => (
<input
key="unique_key_3"
id="unique_id_3"
type="text"
value={value}
onChange={onChange}
/>
)}
></Field>
</form>
)}
/>
);
}
The input is losing its focus after every keystroke. In devtools, I can see the HTML form is created anew every time (it flashes pink). The React component itself however goes through rendering only once.
There are similar questions, however all of them suggest using unique keys. Such a solution doesn't seem to be working here.
Why is the input losing its focus over and over again? How do I fix it?
https://codesandbox.io/s/busy-torvalds-91zln
Since an inline lambda is used for the component, its identity changes every render.
While according to many other questions an unique key should be enough, moving the component function outside the master component fixes it altogether.

How to get value as string, not object

I use react-select inside my Redux form and I want me input filled with my value option, not the entire option.
Today, my form field is {'label':'text', 'value':'a'}. What I want is just a.
Here is my code:
[...]
renderField = data => {
return (
<Select
id={`xxx_${data.name}`}
name={data.name}
options={data.options}
value={data.input.value}
getOptionValue={option => option['value']}
onChange={(value) => data.input.onChange(value)}
onBlurResetsInput={false}
/>
);
};
[...]
render() {
return (
<Field
type={"select"}
component={this.renderField}
options={[{"label":"test1", "value":"a"}, {"label":"test2", "value":"b"}, {"label":"test3", "value":"c"}]}
name={"xxx"}
/>
);
};
So, I don't want the entire option in my form, but only the value of the option.
Do you know how to do that?
Thank you
EDIT
I tried to add a normalize on my field:
normalize={(value) => value.value}
It work but now, the display is wrong...

Sync validation on a radiogroup (v6)

How can I display sync-validation errors for my radiogroup when using the v6 version of redux-form? One option would be to create multiple renderField functions, in which only one (the last one) would display the errors. I currently have it setup like this:
const renderField = ({ input, meta: { touched, error } }) => (
<span>
<input
{...input}
/>
{
touched &&
error &&
<div>
{error}
</div>
}
</span>
);
// Form-component
// I loop trough multiple values
<Field
type="radio"
component={renderField}
id={`${field.name}-${value}`}
value={value}
name={field.name}
/>
<Field
type="radio"
id={`${field.name}-${value}`}
value={value}
name={field.name}
/>
In this way, the errors get presented multiple times (for each value). I could pass an extra prop when it is the last value, to enable the errors for just that field. Although that would work, it feels kinda nasty.
This is an interesting question. Another option would be to write a component that was just in charge of rendering errors.
const renderError = ({ meta: { touched, error } }) =>
touched && error && <div>{error}</div>
Then, after you had rendered your radio buttons, you could do a:
<Field name={field.name} component={renderError}/>

Resources