How to parse untouched fields in react-final-form - reactjs

I have an input for an amount in react-final-form. If it's not filled, I need to set its form value to zero. I can't pass an initial value to it as if it hasn't been filled by the user, the input itself should stay empty.
In react-final-form docs there's a parse function. But it works only if the field has been touched (filled and then cleared by the user). Is there any way to parse untouched fields and set them to zero in form values, without updating the input?
Here is my code:
<Field
name="amount"
component={CurrencyInput}
parse={value => (value ? value : 0)}
/>
And here is the link to my codesandbox.

if by doing this what you are trying to accomplish is that the object displayed in the <pre> has a default value of zero when the input is empty you could use a state variable and inside the parse keep updating its value
const [amount, setAmount] = useState(0);
const onInputChange = e => {
e === "" || e === undefined ? setAmount(0) : setAmount(e);
};
and in the Field tag
<Field
name="amount"
component={CurrencyInput}
parse={value => onInputChange(value)}
defaultValue={amount}
/>
check the codesandbox here:
https://codesandbox.io/s/react-final-form-wreact-number-format-and-parse-22q3n
Hope this Resolves the issue

Related

Access string of selected place in StandaloneSearchBox in react-google-maps/api

I'm wondering how I can access the actual value in a <StandaloneSearchBox ..> component after the user selected it from the autocomplete dropdown menu. I basically want to make it a controlled component.
I tried getPlaces() but that does not give me the actual value visible on the page but rather a bunch of structured data.
Take the example from the official docs (https://react-google-maps-api-docs.netlify.app/#standalonesearchbox), I basically want to do something like:
...
const [inputFieldValue, setInputFieldValue] = useState ("")
const onPlacesChanged = () => {
...
const value = ... // 1. access value
setInputFieldValue (value) // 2. store in state
}
...
<input
type="text"
placeholder="Customized your placeholder"
style={{...}}
value= {inputFieldValue}
/>
...

Getting Default value in React Hook?

I have an input field with a default value
<input type="text" name="default" value="one" />
I'm using react hook to use state
const [def, setdef] = useState({Default:""})
what I want is to set the input default value one to the state
Desired Output
setdef({...def, Default:"one"})
how can I achieve this? I know about the onChange function but I don't think it will work.
any better suggestion is appreciated. thanks in advance
I assume that you need to create a hook with a default string, like this:
const Component = () => {
const [string, setString] = useState("hello") // <-- this is the default value of the input
// Set the hook value into the content of the input
const handleChange = (event) => {
setString(event.target.value);
}
return <input value={string} onChange={handleChange} />
}
The input's content would be "hello" by default, but the user can change it. Delete the onChange event to make it read-only.
(mi comentario estaba en español, perdón por la mala traducción no soy bueno en el ingles)
I think this is what you need
When using hooks one can specify what value it will have by default like this:
const [def, setdef] = useState("one")
by doing what is above you will get the value that I add in quotes when occupying -> def.
<input type="text" name="default" value={def} />
the input will obtain an initial value that will be "one"
and if you want to modify its value you will only have to do this:
setdef("new value")

How to limit number of characters in Field using Redux?

I have Field input and my idea is to user can input only 15 characters.
After 15 characters I want not displaying anything in field. I have tried with normalize but not working. I'm checking with value.length and after 15 characters my state is not updating which is good but I can still entering characters. I want after 15 entered characters, if user put something not to show that in browser. Can anyone help me?
<Field
name={`name`}
placeholder='placeholder'
classes={classes}
component={this.component}
onChange={this.changeHandler}
/>
changeHandler= (event) => {
if(event.target.value.length < 16)
{
this.setState({
myProperty: event.target.value
});
}
For redux-form Field there isn't a props to limitate number of chars. Considering that you are using Field in a form, you could validate the field itself (using validate props as in this example) but still the possibility to add more than 15 chars.
But as you know you could customize your Field using component props. Something like:
<Field name="myField" component={renderField}/>
And in renderField you could use input and in input you have maxlength props.
So your renderField could be something like:
const renderField = (field) => (
<div className="input-row">
<input {...field.input} type="text" maxlength="15"/>
</div>
)
This should solve your problem.
For this you would need a handled value. Pass value={this.state.myProperty} to the Field. So if this property is no longer updated after 15 characters, the value of the field won't be updated either.

Getting doubled value with an onPaste event on an input using React

I have a text input field in my React app and I want to validate its input so I have a validator function working in a handler for the onChange event. I also want to trim whitespace when a value is pasted into the input and then have that run through the onChange validator.
Currently my JSX looks like this:
handleChange(event) {
let { name, value } = event.target
if (typeof this.props.validatorFunction === "function") {
value = this.props.validatorFunction(value) // the validator function in this case is {value => value.replace(" ", "-").toLowerCase()}
}
this.setState({
[name] : value
})
}
handlePaste(event) {
let { name, value, selectionStart, selectionEnd } = event.target
let pastedValue = event.clipboardData.getData("text")
let pre = value.substring(0, selectionStart)
let post = value.substring(selectionEnd, value.length)
value = (pre + pastedValue + post).trim()
this.setState({
[name] : value
})
}
render() {
return (
<input type="text" name="myInput" value={this.state.myInput} onChange={this.handleChange} onPaste={this.handlePaste}></input>
)
}
Regular typing works as expected however, when I paste something such as "test string" I get "test-stringtest string". "test String " with the trailing white-space I get "test-stringtest string ". This works except for the doubling up of the untrimmed but somehow lowercased but not replaced original string. How do I fix this, or what is the proper workflow for this kind of validation using React controlled components?
You need to call event.preventDefault() after handling your paste event. As it is, the paste event is changing the state in handlePaste and then going on to add the pasted text to the input, triggering handleChange.
As requested, I am providing more details on the solution.
It turns out that for my purpose, having an onPaste handler is superfluous. If I removed the onPaste handler, the doubling issue would be resolved, and paste behaviour inherently remains. An example of the code I would write for this today is here: https://jsfiddle.net/tvandinther/sLav0chj/31/
function ValidatedInput(props) {
const format = (value) => typeof props.formatFunction === "function"
? props.formatFunction(value)
: value
return (
<input
value={props.value}
onChange={event => props.setValue(format(event.target.value))}
/>
)
}
Suppose you do need to keep the onPaste handler. In that case, the solution described is to call your shared logic (in this case, formatting the string and setting the state) in both onPaste and onChange handlers but ensure that event.preventDefault() is called in the onPaste handler.

Control Focus of Multiple FormControl Fields

I have a mapped list of input fields:
<FormControl
name={row_index}
value={barcode.barcode}
placeholder="Barcode - then Enter"
onChange={this.onChange}
onKeyPress={this._handleKeyPress}
disabled={barcode.submitted}
/>
I am currently using onKeyPress to handle submit:
_handleKeyPress = (e) => {
if (e.key === 'Enter') {
const name = e.target.name;
const barcodes = this.state.barcodes;
const this_barcode = barcodes[name];
let apiFormatted = {"barcode": this_barcode.barcode, "uid": this.props.currentSession}
this.postBarcodeAPI(apiFormatted, name)
}
}
I am attempting to focus on the next input field after the current one is successfully submitted. React documentation has an example for manually setting focus on a single input field using ref={(input) => { this.textInput = input; }} />. I have tried using this[‘textInput’+‘1’].focus() (using computed property names, but am getting an error that function is invalid.
EDIT
Per Chase's answer, I am linking to the autofocus documentation, although it doesn't work in this case.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/autofocus
My working solution:
const focusing = index === lastSubmittedIndex + 1 ? true : false;
const refText = focusing || index === 0 ? input => input && input.focus() : null;
<FormControl
name={row_index}
value={barcode.barcode}
placeholder="Barcode - then Enter"
onChange={this.onChange}
onKeyPress={this._handleKeyPress}
disabled={barcode.submitted || barcode.apiCalling}
inputRef={refText}
/>
What I corrected in my code:
1) I am supposed to use inputRef instead of ref for Bootstrap's FormControl component, see here.
2) I am using ilya-semenov's very neat code.
Update
I have other buttons on the page, when user presses them and is at bottom of page, page jumps up to top. Not sure why.
Unless you've set a ref with the key textInput1 then this won't work. Another suggestion would be to move all of the inputs into a separate component and then you can use this.props.children to traverse all your inputs and grab the input at whatever position you want.
EDIT:
You can also use the autoFocus prop to determine if an input should be focused or not.

Resources