Redux-form field with input component re-renders on first character causing the keyboard to collapse - redux-form

I have a form which is made using some logic, loading components from an external API.
This was working great using redux-form 6.3.2 and react 16.0.0-alpha.12.
The app is built with expo and I had to update expo SDK to the latest, which updates react to 16.3.1 and forced me to update redux-form. Since I had to update I went to the latest version (7.3.0) which led to some issues in the app that I was able to fix, but for this one I can't find a solution:
The forms is created using fieldArray and Field, so the createElement, after some processing does this:
return fieldObj.fields ?
(<View key={idx} style={style}>
<FieldArray {...fieldObj}
key={idx}
name={fieldObj.name}
component={component} />
</View>)
:
(<Field {...fieldObj}
key={idx}
style={style}
type={fieldObj.type}
name={fieldObj.name}
component={component} />);
And we get component using a formWrapperHOC:
formLib.FormWrapperHOC(formElement, {
onChangeCB,
onBlurCB,
stylesKeys,
formName,
extraProps,
})
which in turn does some things until it renders:
//FormWrapperHOC render method:
render() { return (<WrappedComponent {...this._massageProps()} />); }
So when I insert the first character in this input I see the events:
##redux-form/FOCUS
##redux-form/CHANGE
##redux-form/UPDATE_SYNC_ERRORS
##redux-form/REGISTER_FIELD
##redux-form/UNREGISTER_FIELD
I tried removing validations, so UPDATE_SYNC_ERRORS is not called, but item still rerenders.
Another thing that caught my eye is that the field is registered and later unregistered.
I end up with the input field and the character I entered, but keyboard is collapsed. If I focus on the field again everything works as expected: No call to UPDATE_SYNC_ERRORS because the field already has some content on, only CHANGE is triggered.
Since this works fine with redux-form 6.3.2, I'm pretty sure I need to make a change in my code for it to work with redux-form 7.3.0. Thing is, I was not able to find where is the issue, so any help or lead for where to look will be greatly appreciated.

Related

MUIInputLabel does not grow when TextField is empty

The TextFields in the Material-UI docs has the label which grows and shrinks depending on whether there's a value in the field.
Rather than a user input, I am trying to use JS to reset my TextField to "" when a button is pressed. This means if a user has keyed data into the TextField, if they press the reset button, the field is cleared while the label grows to refill the field.
What is happening is that while my data is cleared, the label remains small.
Where am I going wrong with this?
I've read that it's related to something called shrink, but I dont understand how its called.
A portion of my code, built using Material-UI and ReactJS
EntryField component
<TextField onChange={inputChangedHandler} label={props.label} value={props.value} type={props.type} required={props.required} name={props.name} id={props.id} inputRef={props.propsRef} />
Form component, which uses the EntryField component above, as well as the ReactJS
const refNumRef = useRef();
const [objRefNum, setRefNum] = useState();
(...)
function resetData(event){
setRefNum('')
}
(...)
<EntryField label="Ref Number" type="text" editData={setRefNum} value={objRefNum}
id="input_refNum" name="refNum" propsRef={propRefNumRef} />
So....after posting my question, I made more trial and errors and I somehow managed to get it to work; Im not sure why.
But the main change I made was setting a default to the useState like so
const [objRefNum, setRefNum] = useState("");
And somehow this managed to fix not just this issue with the TextField, but an issue Ive been having with a Select statement as well, where I had trouble resetting it to a default value.
I will eventually have to figure out how to declare this programmatically based on API calls where the default value will change based on the results........but this is fine for now.

VeeValidate 4: two forms on one page

I have a Vue component in a Vue component, and both of them contain one form each that I want to validate individually.
<form #submit="submitLogin">
Input fields and button
</form>
<OtherComponent />
Where the other component has a similar form. It appears when I use handleSubmit the main component will try to handle all the input fields, and the handleSubmit in OtherComponent does not work at all.
const { handleSubmit } = useForm();
I also tried a workaround where I instead used validate, manually ran a validation on button clicks and checking meta valid to see if the form was valid.
const { validate, meta } = useForm()
The same thing happened here, since both components use validate useForm it messes up the OtherComponent's one. When I check the meta it says it's always valid even if it isn't.
I have thought about putting them in the same component but don't see how that would make a difference.
Is there a way to achieve this or do I have to someone work around it?
I had the same problem, you can track this issue on vee-validate github:
https://github.com/logaretm/vee-validate/issues/3204
Currently, to avoid this bug you have to discharge a wrapper component for each of your form, like this:
<ComponentWithForm />
<AnotherComponentWithForm />

How to enable v-model on custom component?

I'm trying to wrap a TexField ui to a new custom component so that I can add extra functionalities and reuse the component within the project. I want it to still have the v-model binding so I implemented the following:
:text="text"
and
#textChange="(update)=>{$emit('textChange', update.value)}"
Wherein "text" is its prop named and exposed exactly as a normal TextField prop.
The pattern should work on web but I don't know if it's possible on nativescript vue component. Please have a look at the code I made in playground: https://play.nativescript.org/?template=play-vue&id=Ikap1R&v=1
It's not working. Please help if you know the solution.
Thanks
There is nothing you have to do specifically for {N}, if you know how it works with Vue.js, you got it.
All you have to do is, use a value prop for input value and emit input event on change.
Updated Playground

Increase performance on Angular2 inputfield

I have a list of components that contain dates(formatted with toLocaleString()) and other things. On top of them there is a component for creating new components, wich contains a form with some inputfields built with angulars FormBuilder.
When I type fast the validation lags and the text I'm typing isn't displayed immediately.
I assume that Angular is rerendering all components, because if I don't display the date in the other components I can type pretty fast without lags.
Is there a way to only rerender the input field I'm typing in, since all other components cannot change or is toLocaleString() the problem?
Is there a way to only rerender the input field I'm typing in, since all other components cannot change
Yes, for the components that will not change, set the change detection strategy for those components to OnPush. An OnPush component will then only be checked for changes if
any of its input properties changes
it fires an event (e.g., a button click)
an observable (which is an input property or a local-to-the-component property) fires an event, and | async is used in the template with the observable (see plunker in the comments below this answer)
import {Component, Input, ChangeDetectionStrategy} from 'angular2/core';
#Component({
...
changeDetection: ChangeDetectionStrategy.OnPush
})
Also consider listening for changes to your input by subscribing to the valueChanges Observable Angular makes available on your form element if you use ngFormControl. You can then use debounce() to only process changes every second or whatever time frame is appropriate:
<input type=text [ngFormControl]="input1Control">
constructor() {
this.input1Control = new Control();
}
ngOnInit() {
this.input1Control.valueChanges
.debounceTime(1000)
.subscribe(newValue => console.log(newValue))
}
See https://stackoverflow.com/a/36849347/215945 for a working plunker.
That's a known issue https://github.com/angular/angular/issues/6311
See also
https://github.com/angular/angular/issues/5808
https://github.com/angular/angular/issues/7822
https://github.com/angular/angular/issues/7971
There is also a pull request with a proposed fix, but seems not to be included in the latest beta release.

Knockout - Disabling the default behavior of updating model when using binding value with form element

Knockout has the default behavior of updating the associated model if you change your focus (e.g. by clicking outside the input control) after editing the value inside an input control, populated by a binding of type Value.
Here is the link to the official documentation page explanation, section Parameters:
http://knockoutjs.com/documentation/value-binding.html
Do you know a way to disable this default behavior ?
The reason behind this : Im using Models that can tell if their last update requires persistent backup by comparing the previous value to the new one.
I would like to listen to the key up event on my form inputs but if I do that, knockout triggers twice event (the default one + the key up) to update the Model and the second one is basically telling my Model to replace the value by the same value because it is already updated, which it translates to "there is no need to do persistent backup since the value didnt change".
I would gladly appreciate any help or suggestion, since Im stuck and can't find a way around :)
EDIT
Couldnt reproduce the error with bare backbone code. It seems as "super cool" said that valueUpdate should override the default Blur event that triggers when you use form controls with binding Value.
It may be a bug introduced by the library Knockback that I use to create the ViewModel.
Despite all this, just replacing the binding Value by the binding textInput did the trick. Thank you all.
Don't listen to the event, subscribe to updates, which won't fire unless the value is changed. Using the textInput binding will register every change to the value, even those done using menu items like cut and paste, when they happen.
Equivalently, you can use the value binding along with valueUpdate: 'input'
vm = {
myvar: ko.observable(),
updates: ko.observableArray()
};
vm.myvar.subscribe(function(newValue) {
vm.updates.push(newValue);
});
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input data-bind="textInput: myvar" />
<div data-bind="foreach: updates">
<div data-bind="text: $data"></div>
</div>

Resources