Getting the value of an uncontrolled Material UI TextField - material-ui

From the documentation, it describes having an uncontrolled field by omitting the value and onChange attribute. The React website says to use a ref on any uncontrolled inputs, but doing this with a TextField only refs its container, a div. What is the recommended way of retrieving the value of an uncontrolled TextField in Material UI? I could use a querySelector to find the element, but that doesn't seem like a proper way.

use inputRef prop on TextField
<TextField inputRef={ref} ... />
you can access its value by this: ref.current.value

A clarification: value deals with controllability, and onChange deals with observability. They are separate from each other.
You only make inputs controlled by setting the value prop. Setting the onChange prop can be used separately to observe the input changes without acquiring control over it, thus, achieving what you are asking for.

The way to provide a ref to the rendered input is via the innerRef prop on the TextField component. Here's the a link to the API where it states that. From there you can access the value of the input as such, ref.current.value
<TextField innerRef={ref} />

Related

react testing library rendering , child prop is undefined

Let's say I want to check this component render its child with the right initial props
const { container } = render(<Header/>)
Where is
<div> <SomeChild custom-prop=innerHeaderVariableLikeInitialState /> </div>
Before I can try to check anything when I run my test I get the prop 'custom-prop' is marked as required but it's value is undefined (I use prop types)
So it means the react-testing-library doesn't initialize its child componenent ?
How to manage this ? I feel I'm not taking this with the right angle
Thanks
What you're looking for is probably container.firstChild.
However, testing for the presence of certain props goes against the "don't test implementation details" approach of react-testing-library. Really, there's no way to do that with the rendered output, as it's all DOM elements, not React components. Instead, consider what user-facing elements you could look for, like text, accessibility labels, etc. How can you verify the user is seeing what you expect them to see?

How to bind integer Input value to Slider

I want to have a Slider and an Input control, both for one specific value.
The user should be able to use either the input field or the slider to input his value.
If the user changes the value on the Slider, the input field should show the Slider's value. And if the user inputs something in the input field, the Slider should move to the corresponding value.
Currently, I am creating a JSONModel with the value as a property to bind:
let model = new JSONModel({
valueName: 10
});
settings.setModel(model);
Now, when I am changing the value on the slider, the update of the input field is working fine. But if I'm entering a value in the input field, the Slider does not move to the value.
Why is that so and how do I solve my problem?
<Slider value="{/valueName}" step="10" width="200px" />
<Input value="{/valueName}" type="Number" width="50px" />
Since the given solutions only worked for integer values a follow up question for float values was created here
I was baffled by this at first. The reason appears to be that the value is saving as a string (in spite of you explicitly specifying number or clearly binding the value in the initial model to a numeric value).
I checked this by handling the liveChange event off the Input, retrieving the model value of valueName, doing a parseInt on the value and then setting the Slider to that value.
This causes the slider to update as I change the Input.
Controller:
handleChange: function(){
var slider = this.getView().byId("slider");
var val = this.getView().getModel().getProperty("/valueName");
slider.setValue(parseInt(val));
}
XML View:
<Slider id="slider" value="{/valueName}" min="0" max="100" step="10" width="200px" />
<Input textAlign="Center" value="{/valueName}" type="Number" width="50px" valueLiveUpdate="true" liveChange="handleChange"/>
The caveat was if I wanted to update the slider to, say, 70 I would need to key in the 0 first (as the slider settings as they stand convert the value to min (0) or 10 the moment I type a number - given the correct behaviour of liveUpdate). There are ways to work around this but I thought I'd get you the answer and you can figure out what to do from there.
Ultimately i think this is a bug. EDIT - this is not a bug - please refer comment by Boghyon below this Answer
The user should be able to use either the input field or the slider to input his value.
In case you were not aware, you could use the built in Tooltip input feature:
<Slider
showAdvancedTooltip="true"
showHandleTooltip="false"
inputsAsTooltips="true"
/>
Gives you this:
Slider awaits a value of type float.
The input field, however, evaluates inputs as string.
You can solve it declaratively by assigning an appropriate type to the binding info object:
Either assign sap/ui/model/type/String* to Slider's value binding type ⇒ Formats the string value from the model to a float type prior to passing the value to the Slider.
Float value manipulated from the Slider will be converted back to a string value before storing it in the model as a result of two-way binding with the String type.
Or assign sap/ui/model/type/Float* to Input's value binding type ⇒ Stores the value as number in the model. The Slider can then use the number value directly.
Here is a demo of the above approaches: https://jsbin.com/sodihub/edit?js,output
Using the type feature in binding will allow parsing, formatting, and even validating the model value before updating the control while still keeping the two-way data binding mode.
* In case of binding with ODataModel, require sap/ui/model/odata/type/Decimal|String instead!

Mask input for sap.m.Date(Time)Picker

With the sap.m.DateTimePicker, it's possible for a user to either select a value from the drop-down list or enter it manually. I'm wondering if there's a way to add a mask to the manual input box that matches the valueFormat of the DateTimePicker.
I know there's a sap.m.MaskInput as well, so maybe there's a way to combine the two elements.
There is a new private module named sap.m.MaskEnabler which the sap.m.InputBase (i.e. DateTimePicker) is supposed to make use of.
(MaskEnabler) should be applied to the prototype of a sap.m.InputBase.
The mask feature is currently enabled only in sap.m.TimePicker (v1.54). According to this commit message, however, the same feature will arrive to the Date(Time)Picker as well:
This change prepares for refactoring of DatePicker and TimePicker so the
common code of both pickers can be moved to a new common control that
they may extend.
Therefore, if it's not urgent, and depending on your project, I'd not create a new custom control and then throw it away once the mask feature has arrived.
I'll update my answer when it's available.
Until then (and even afterwards), you can still guide the user to enter the data in the correct format via OData binding type sap.ui.model.odata.type.DateTime:
<DateTimePicker
value="{
path: 'myODataModel>myDateTime',
type: 'sap.ui.model.odata.type.DateTime',
constraints: {
isDateOnly: true,
displayFormat: 'Date'
}
}"
minDate="{...}"
maxDate="{...}"
/>
In contrast to formatter, type allows us to keep two-way data binding.
The entered value is automatically intercepted from updating the model data when...
It could not be parsed due to an invalid format (fires parseError)
It could be parsed but the constraints were violated (fires validationError)
If you enable handling UI messages
additionally, the framework will then take care of creating the appropriate
message for the user:
Example: https://stackoverflow.com/a/48482544
I think the only way to combine the two sap.m.DateTimePicker and sap.m.MaskInput is to develop your own control . Documentation : https://sapui5.hana.ondemand.com/#/topic/91f1703b6f4d1014b6dd926db0e91070.
Another way is to just use the Placeholder of the DateTimePicker Input field. This does not provide the same functionality as a MaskInput, but helps the user which valueFormat is expected in the input when entering it manually.
If you have a binding in your input box, you could set the type in the binding to eg. sap.ui.model.type.Date. This way you get some automatic formatting when field validation is triggered. There are other types available and you could inherit from sap.ui.model.SimpleType to code your own.

Pre-populating form fields with model data in Sightly/HTL

I've tried all the HTL context parameters (even 'unsafe'). When I inspect the input, I can see the value intact, but you can't see the value pre-populated in the field. I tried different types of values, different contexts, and different types of input fields. [AEM 6.2]
<input type="email" name="senderEmail" value="${userProfile.email # context='text'}"/>
If the value is rendered in page source and also visible in browser inspector, could it be that it's hidden by some weird CSS? Something like color:transparent
There are many possible causes. I'll pitch in one, to help get you thinking. Is userProfile available via the use api?
I've made this mistake before:
<div data-sly-use.bean="com.beans.Bean">
${bean.value}
</div>
// ... other code
${bean.value}
The "Bean" isn't available later, outside it's host element.
If I understand your question correctly this isn't actually about HTL, but rather about the HTML input element itself. You have an input element with a value attribute set, yet that value is not displaying in the box. If that's correct, then I'd recommend doing some investigation around HTML input value not displaying when set, rather than sightly context issues.
Some possible answer would include css styles hiding the input text or javascript clearing out the values after page load. There are certainly more potential causes, but we'd need to know more about your page to provide a better answer.
To do some of your investigation you can try loading a component with only that input in it and see if that works, that would eliminate any css or js executing elsewhere on the page.

Why after set formatter of a property binding of TextField, the json model binding becomes "oneway"?

I'm writing an application using XML view. There is a JSON Model 'data' set on the view, when I put a text field like below, I can get the updated value from user input.
<TextField value="{path: 'data>/xxx'}" />
But if I put a formatter in the binding like below, then it's impossible to get the updated value back.
<TextField value="{path: 'data>/xxx',
formatter: 'abc.util.formatter.yyy'}" />
Why is that? How to use JSONModel TwoWay binding and formatter at the same time???
The binding mode switches to OneWay as formatters do not support bi-directional data flow, as they are used for formatting property values for the output. A TwoWay binding includes also parsing and validating input before it is written to the model. If you need this, you should use a type instead. This is the same for all model type, not only the JSONModel.
Maybe your binding sytle is problem.
Can you try this in your index.
data-sap-ui-xx-bindingSyntax="complex"