How to unregister a field in in react-final-form? - react-final-form

There is documentation on how to register a field but I don't see anything on how to unregister a field after it's been rendered. Anyone know how I can do this.

destroyOnUnregister Optional.
boolean If true, the value of a field will be destroyed when that
field is unregistered. Defaults to false. Can be useful when creating
dynamic forms where only form values displayed need be submitted.
So just set this on your Form:
<Form destroyOnUnregister .... />
https://final-form.org/docs/final-form/types/Config#destroyonunregister

You just unmount (stop rendering) the Field component or the component using useField().

Related

Submitted value scope

I have a primitive view: a form containing a validatable text input component and a command button. The input value is pointing to a session-scoped backing bean.
I open the page, enter an invalid value and submit the form: after the postback, a validation error is appearing and the input component is displaying the submitted value which did not pass validation. The model value in my session-scoped bean is left intact, as expected.
Ok, now I open another tab in the browser and open the same page. To my surprise, the input component is displaying the submitted value from the first tab. I've been supposing the view state to be new at another GET request and the plain model value from my session-scoped bean to be shown instead.
If I use a view-scoped bean instead of a session-scoped one the model value is being rendered for the input component in the second tab, not the submitted value from the first tab.
Is the submitted value not the part of the view state and kept somehow along with the model? Or is its scope tuned up in some smart way depending on the referenced bean's scope?
Sorry in advance if this question is stupid but I will be very grateful for removing my misunderstanding.

How to serialize the checkbox in a form into Json data

We know that in MVC, a CheckBoxFor will generate a checkbox with a value="true" and a hidden with a value=false. Both input controls will share the same name.
It is very reasonable because the form will be able to POST a false value if the box is unchecked. And the model binder will ignore the hidden input when the checkbox return a true.
But now i have overridden the form submit event in order to send the form data into a WebAPI controller in JSON format.
When serializing the form data, there is no mechanism to parse the relationship between the checkbox and the hidden correctly. Therefore, when unchecked, it returns a false, which is okay. But when checked, it returns a {true, false} instead of true, because the serializeArray() function goes through every input and find two values goes to a same name.
The question is: What is the best way to correct it?
My solution to this problem was to write my own HtmlHelper method that renders a single <input type="checkbox" /> tag. Any other solution just seemed too hacky.
You can use dotPeek or .NET Reflector to look at how the Microsoft Team created the HtmlHelper.CheckboxFor method if you need any help accomplishing that task.
The 2 tag approach was taken to prevent MVC action parameters from throwing an exception when a "bool" parameter did not have a matching parameter sent to the controller (an unchecked checkbox doesn't send any value).

asp.net mvc disabled text box updated by javascript does not post new value

I am using a strongly typed model for my view. I have a disabled text box whose value I update using javascript. The textbox is rendered using this
<%: Html.TextBoxFor(model => model.TotalAmount, new { disabled = "disabled"})%>
This renders a textbox with NAME and ID as 'TotalAmount'. TotalAmount is also a property on my model that binds to this view.
The javascript to update its value in the view is like this within its function:
document.getElementById('TotalAmount').value = {assigning new value here};
The function does get called and I can see the value in the disabled textbox when I change some value in another editable textbox. However, when I post this form to my action method as below :
[HttpPost]
public ActionResult Process (ProcessVM FormPostVM)
{
}
the disabled textbox property [TotalAmount] still has the old value but the editable textbox which I modified contains the new value I entered. Why does the disabled textbox not contain the javascript updated value?
I tried using
ModelState.Remove("TotalAmount");
in the action method above, but as I already figured it didn't work.
Any clues, tips?
Thanks for your time....
HTML input elements such as textboxes that have the disabled="disabled" attribute will never send their values to the server when the form is submitted. If you want to send the value to the server while still disabling the user from changing it you could make the textbox readonly:
<%= Html.TextBoxFor(model => model.TotalAmount, new { #readonly = "readonly" }) %>
Disabled inputs are never sent in a form submit, try using readonly attribute instead or hidden inputs
Disabled fields don't get posted. Try having a hidden form field that will send the value to the server, and set both TotalAmount and the hidden form field. On the server, use the value for the hidden field instead.
On a side note, since this looks like the order total, this is something I would recalcuate on the server rather than opening up the possibility of someone hacking the html and getting a discount on their product.
EDIT:
To the other's points, I'd forgotten about the readonly attribute. That will work too.
If you change it to use readonly rather than disabled, then this should give you the same functionality, but post the value.
Browsers don't post values back in disabled input controls, as you've discovered. Probably the easiest way to work around this is to hook onto form submission, and re-enable the input as the form is being submitted; the user won't have a chance to edit the value, and it should get posted with the rest of the request.
i think the last issue described it : please check it out :
Retrieving the value of a asp:TextBox

How to mimic MVC's checkbox -> bool model binding?

I've got an editor template which renders out a checkbox:
#Html.CheckBoxFor(model => model.Follow)
Which renders something like this:
<input checked="checked" data-val="true" data-val-required="The Follow field is required." id="Follow" name="Follow" type="checkbox" value="true" />
<input name="Follow" type="hidden" value="false" />
AFAIK the hidden field is something to do with catering when an unchecked box isn't sent to the server or something.
Anyway, if i take a look at the Request.Form["Follow"] when the checkbox is checked, i see a value of "true,false".
How do i coerce a bool from this value? Do i simply ignore the second field? (e.g the hidden field).
I'm doing this is a base controller (protected method, invoked from child controller), so i don't have a strongly-typed view model, only the raw Request object.
Can anyone help? Or alternatively, if someone could point me to where in the MVC source code this happens, i could take a look myself, but not sure where to start looking.
You are correct the hidden field is just so the form will be submitted to the server. Because if the form had just checkboxes that are not checked then nothing will be submitted and the server would not know to set them to false.
You only require 1 hidden field per form, you do not need one per checkbox. But if your making your own control it is hard to tell if a hidden textbox is already on the field or not. If you know you are always going to have a textbox or select list etc somewhere else on your forms you do not need a hidden textbox at all
You can rename your hidden textbox to anything name it "dummy" or something different to the checkbox name so Request.Form["Follow"]; will only return the value of the check box not need to split. You never need to check the value of the "hidden textbox".
On a side note you shouldn't be using Request.Form["Follow"] you Action method should have a parameter like this instead "bool? follow"
MVC helper renders checkbox input control with two input fields, the checkbox and the hidden, because the browser do not send a value for checkbox input field if the checkbox is not selected. If you do not use auto mapping, you need to parse the input value that you receve from your form.
Use this simple rule to detect the checkbox:
var rawFollow = Request.Form["Follow"];
if (rawFollow.Contains("true"))
{
// do something
}
As far as i know, the extra hidden field is because if the checkbox is NOT checked, that input will not be submitted with the form and therefore we need the hidden field with the value of false.
So the only solution is can think of is this:
var rawFollow = Request.Form["Follow"];
var rawFollows = rawFollow.Split(',');
if (rawFollows.Count() > 1)
{
rawFollow = rawFollows[0];
}
But this seems hacky (and what about the order of the elements on the page, what if for some reason the hidden field was FIRST, then it would always evaluate to false), which is why i'm wondering how the MVC source does this.

Multiple controls in MVC view that modify same model value

I have a field in my model - call it 'distance' - and I want to write a view that contains both a checkbox and a textbox.
If the checkbox is checked, the textbox becomes disabled and 'distance' gets the value 0 when the form is submitted.
If the checkbox is not checked, 'distance' gets whatever value is in the textbox when the form is submitted.
Anybody have any guidance how to do this? It's the logic of assigning a model value based on the state of both the controls that confusing me...
The UI behaviour can be accomplished with Javascript via an onclick event handler on the checkbox. The only value you need to submit is the input field whose value will be set to 0 or whatever is set manually.
With jQuery you would have:
$('#checkbox_id').click(function() { $('inputfield_id').val('0');
The Model behavior depends on what the checkbox represents. If it's an actual property on the Model, then you will need to check the value server-side as well as (optionally) using aleemb's javascript method.
If a check in that field simply represents a distance of zero, then aleemb's method will suffice.
Aleemb's answer worked like a charm, with a couple of minor modifications:
$("#Distance_checkbox").click(function() {
if ($(this).is(':checked')) {
$("#Distance_textbox").val(0);
$("#Distance_textbox").attr("disabled", true);
}
else {
$("#Distance_textbox").val("");
$("#Distance_textbox").attr("disabled", false);
}
});

Resources