MUIInputLabel does not grow when TextField is empty - react-hooks

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.

Related

history.replaceState() not working with history.scrollRestoration = 'auto' in Svelte/Sapper

I am using history.replaceState() to update the query params of my page without causing a page reload as suggested in this SO answer.
function setQueryParam ({ name, value }) {
const params = new URLSearchParams(window.location.search)
params.set(name, value)
history.replaceState({}, '', decodeURIComponent(`${window.location.pathname}?${params}`))
}
I am also storing the scroll position of the user with the following line:
history.scrollRestoration = 'auto'
When navigating from one page to another, scrollRestoration works fine - the scroll position is maintained between pages. However, after I change the query params with my setQueryParam function, scroll restoration no longer works.
Why is this happening?
Note: the same code works fine outside of Svelte/Sapper, using HTML and JavaScript only.
As a client-side router, Sapper has to hijack scroll management & restoration a good deal to emulate the behaviour you normally get when you fully reload the browser on each page change.
To do that, it uses history's state to know the scroll position to restore.
When you're using history.replaceState, you're changing the state (it's the first argument you place to replaceState). And so, Sapper don't find its restore scroll data when you later pop the state.
You can try to manually preserve the history state like this:
// notice the first argument
history.replaceState(history.state, '', decodeURIComponent(`${window.location.pathname}?${params}`))
I don't think history.scrollRestoration actually has any effect in Sapper.

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

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.

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>

How can I validate my Firefox extension's preferences?

What is a generally accepted way to validate preference values in a Firefox extension, specifically when using the prefwindow mechanism in XUL?
I am introducing some new preferences in one of my extensions that I would like to validate before the preferences window is closed. If there's an error, the user should be allowed to correct the issue, and then proceed. I see that the prefwindow element has two potentially useful functions to help in this regard:
onbeforeaccept
ondialogaccept
The former seems to have an associated bug (Bug 474527) that prevents the prefwindow from remaining open when returning false from that function. This is bad in that it doesn't give the user an opportunity to immediately correct their mistake.
The latter appears to have the problem that the preferences get saved prior to exiting, which leaves the preferences in a bad state internally.
In addition, the prefwindow mechanism supports the browser.preferences.instantApply option, in which preference values are written immediately upon updating the associated control. This makes validation extra tricky. Is there a clean way to validate custom preferences in a Firefox extension, allowing the user to correct any potential mistakes?
Normally you would want to validate the preferences when they are changed. That's something that onchange attribute (and the corresponding change event) is good for:
<preference name="preference.name" onchange="validate(this);"/>
The event is fired after the preference value changes. There are two drawbacks:
In case of instantApply the new preference value is already saved, too late to validate and decline.
For text fields the preferences are saved every time a new character is typed. This becomes ugly if you report validation failure while the user is still typing.
You can solve the first issue by intercepting the change events for the actual input fields. For example, for a text field you would do:
<input preference="preference.name"
oninput="if (!validate(this)) event.stopPropagation();"
onchange="if (!validate(this)) { event.stopPropagation(); this.focus(); }"/>
So changes that don't validate correctly don't bubble up to the <prefpane> element and don't get saved. The events to listen to are: input and change for text fields, command for buttons and checkboxes, select for the <colorpicker> element.
The second issue is tricky. You still want to validate the input when it happens, showing the message immediately would be bad UI however. I think that the best solution is to assume for each input field initially that it is still "in progress". You would only set a flag that the value is complete when you first see a blur event on the field. That's when you can show a validation message if necessary (ideally red text showing up in your preference page, not a modal prompt).
So to indicate what the final solution might look like (untested code but I used something like that in the past):
<description id="error" hidden="true">Invalid preference value</description>
<input preference="preference.name"
_errorText="error"
onblur="validate(event);"
oninput="validate(event);"
onchange="validate(event);/>
<script>
function validate(event)
{
// Perform actual validation
var field = event.target;
var valid = isValid(field);
// If this is the blur event then the element is no longer "in progress"
if (event.type == "blur")
{
field._inputDone = true;
if (!valid)
field.focus();
}
// Prevent preferences changing to invalid value
if (!valid)
event.stopPropagation();
// Show or hide error text
var errorText = document.getElementById(field.getAttribute("_errorText"));
errorText.hidden = valid || !field._inputDone;
}
</script>
If you want to validate values as soon as the field is changed so you can handle the instantApply case, you could hook into the change events for the individual fields (e.g. oninput for a textbox). Display an error message and force the focus back to the field if the value is invalid. You can either set it back to a valid value automatically or block the user from closing the dialog until it is fixed.

Resources