Using react-hook-form, how to programmatically modify values of inputs , depending on a selection? - react-hook-form

Sounds simple, but I couldn't find a hello-world example of this, despite the richness of the doc. The closest I could find was in https://react-hook-form.com/advanced-usage, in the Working with virtualized lists section, but that relies on another module react-window, which introduces further complexity.
I want to allow the admin user to create-update-delete a list of products, with various properties.
My current code in JSX looks like this, I'd like to take advantage of error handling etc from react-hook-form:
<ol >
{products.map((row, index) => (
<li
className={index === selectedProductIndex ? "selected" : ""}
key={index}
id={index} onClick={handleSelectProduct}>
{row.name}
</li>
))}
</ol>
<form onSubmit={handleSaveProduct}>
<p>Product name: </p>
<input name="productName" type="text" value={selectedProductName}
onChange={handleEdit_name} />
(... more properties to edit here)
</form>
The handlers save the values of selectedProductName, selectedProductIndex, etc in useState, in a database via axios, etc.
I'm handling the values of each field individually in the useState, which I'm aware is laborious and heavy-handed.

Well the answer was quite simple, although it took me a while to figure it out.
In most of the examples, the onChange or onClick handlers don't use the event object, but nothing prevents you from adding it in. Then there's the setValue function to set the other control's value. Here's the code of a hello-world example. It offers one dropdown and one input field, the input field updates to match the selected value of the dropdown.
import React from "react";
import {useForm} from "react-hook-form";
function Test() {
const {register, handleSubmit, errors, setValue} = useForm();
const mySubmit = data => {
console.log(data);
}
return (
<div>
<form onSubmit={handleSubmit(mySubmit)} className="reacthookform">
<select name="dropdown" ref={register}
onChange={(ev) => setValue("productName", ev.target.value)}>
{["AAA", "BBB", "CCC"].map(value => (
<option key={value} value={value}>
{value}
</option>
))}
</select>
<input name="productName" defaultValue="AAA" ref={register({required: true})} className="big"/>
{errors.productName && <p className="errorMessage">This field is required</p>}
<input type="submit" value="Save product"/>
</form>
</div>
);
}
export default Test;

Related

How do I use multiple submit buttons with react-final-form?

I want to build a form using react-final-form that has multiple submit buttons, where each submit button sets a different value in the form. Essentially, I want to create a form that looks something like this in rendered HTML:
<form>
Are you over 18 years old?
<button type="submit">Yes</button>
<button type="submit">No</button>
</form>
However, I can't figure out how to make react-final-form treat these different submit buttons as setting values in the form. I tried combining component state, <input type="hidden">, and onClick handlers, like this:
class FormWithMultipleSubmits extends React.Component {
state = {
value: undefined
};
setValue = value => this.setState({ value: value });
render() {
return (
<Form>
Are you over 18 years old?
<Field
name="adult"
component="input"
type="hidden"
value={this.state.value}
/>
<button type="submit" onClick={() => this.setValue(true)}>
Yes
</button>
<button type="submit" onClick={() => this.setValue(false)}>
No
</button>
</Form>
);
}
}
However, that doesn't seem to work -- probably because the value property on the <Field> component is only used for checkboxes and radio buttons.
Can someone give me a nudge in the right direction, for how to solve this properly?
Here's a Sandbox that shows how.

How to change " asp-action=" with your selected Viewbag .Net Core 2.0

I am trying to change the "asp-action= ", unfortunately I could not find anything on the internet...
Currently I am working with a ViewBag where I can select a value from that list.
What I want is: I want to put that selected value from the ViewBag in the "asp-action= ( here ) "
Image of my index
Image of my Post method
<form method="post" enctype="multipart/form-data" asp-controller="Parser" asp-action= "PostDrone">
<div class="col-md-10">
<p>Upload one or more files using this form:</p>
<select asp-items="#(new SelectList(#ViewBag.listofitems ))"></select>
<input type="file" name="files" multiple />
</div>
</div>
<div class="form-group">
<div class="col-md-10">
<input type="submit" value="Upload" />
</div>
</div>
For example:
I want the "asp-action=" have the string value "PostSchoen" if I selected PostSchoen from the viewbag selectlist
I hope it is understandable what i said
What you wants to do it should doing by client side development with JS
But you have three ways:
1) You can change it by using JS
here an example with Jquery
need add it to onReady function this will change action to option val
<script>
$(function() {
$("select").change(function (){
//set form action to option val or get to whatever you need
$(this).closest("form").attr("action",$(this).val());
});
});
</script>
2) Send data to one contoller method then switch it by your select or other options
change in view
<select name="typeOfUploading" asp-items="#(new
SelectList(#ViewBag.listofitems ))"></select>
change in controller
PostDrone(List<IFromFile> files, string typeOfUploading)
{
//and use typeOfUploading this will be selected value from your select list
}
3) Firstly provide for user this data send choise, that generate him correct view with needed action

Render selectManyCheckbox without HTML table

is there a way to remove the table out of rendered html that is created by the h:selectManyCheckbox tag in server faces?
I am using twitter bootstrap and i placed the checkboxes inside a dropdown menu:
<ul class="dropdown-menu dropdown-menu-form">
<li><label class="checkbox"> <input type="checkbox" />
Activated
</label></li>
<li><label class="checkbox"> <input type="checkbox" />
Deactivated
</label></li>
</ul>
So the generated html table destroys the layout ...
You could just render a bunch of <h:outputLabel><h:selectBooleanCheckbox> inside <ui:repeat>. This way you've markup freedom. You'll only need to alter the model from e.g. List<T> to Map<T, Boolean> to represent the checked values and then loop over the map afterwards to collect checked ones.
A ready-to-use component is Tomahawk's <t:selectManyCheckbox> which has an additional layout attribute value of spread.

select checkbox with hidden input type

Folks,
I am using watir-webdriver, I have a piece in my HTML DOM which gets generated on the fly when I enter some credentials, this piece has a bunch of checkboxes, the number of checkboxes vary, I have to select one checkbox, below is an example of this, here I want to select the second checkbox(the one that has value "BS" for the input type hidden but the value for input type checkbox is same for all):
<li class="dir">
<input type="checkbox" value="1" onclick="$(this).next('.should_destroy').value = (this.checked?0:1)" name="should_not_destroy">
<input class="should_destroy" type="hidden" value="1" name="import[dir_attributes][][should_destroy]">
<input type="hidden" value="" name="import[dir_attributes][][id]">
<input type="hidden" value="Automation" name="import[dir_attributes][][path]">
<span class="dir_mode">Include</span>
Automation
</li>
<li class="dir">
<input type="checkbox" value="1" onclick="$(this).next('.should_destroy').value = (this.checked?0:1)" name="should_not_destroy">
<input class="should_destroy" type="hidden" value="1" name="import[dir_attributes][][should_destroy]">
<input type="hidden" value="" name="import[dir_attributes][][id]">
<input type="hidden" value="BS" name="import[dir_attributes][][path]">
<span class="dir_mode">Include</span>
BS
</li>
I may be able to do this with XPATH, but wanted to try a non XPATH solution. The input type hidden has the appropriate value that I need, for example above the second checkbox has value "BS" for input type hidden. I tried to use the hidden method like this:
h = ##browser.hidden(:value, "BS")
h.select
But I dont know what to do after this. I am trying to select the checkbox based on the value of the hidden element. Any feedback is much appreciated.
I would suggest using the visible elements instead. I think it makes it easier to read the test and seems more stable.
Try:
##browser.li(:class => 'dir', :text => /BS/).checkbox.set
Here we go, I think this will do it
Since you have to select the checkbox based on the hidden, you're going to have to go up a level to the containing li, then drill down to the checkbox
#browser.hidden(value: 'BS').parent.checkboxes.first.set

HTML.CheckBox(string) evaluates to two HTML elements instead of one

The code
<%=Html.CheckBox("SendEmail") %>
evaluates to two HTML elements when it's rendered
<input id="SendEmail" name="SendEmail" type="checkbox" value="true" />
<input name="SendEmail" type="hidden" value="false" />
Is this by a bug? Or by design? If it's by design, why?
I was having some trouble this morning with retrieving selected values from a checkbox group in my MVC app. I sent this out to my team and thought I'd share it with everyone else.
When posting back values for checkboxes, the standard behaviour of all browsers is to completely leave out un-checked checkboxes from the post back. So if you have a checkbox that isn’t checked then nothing shows up for this in Request.Form. This is a fairly well-known phenomenon that most developers account for.
In ASP.Net MVC when you use Html.Checkbox, it attempts to get around this and ensure that you have a value posted back (in this case ‘false’) for un-checked checkboxes. This is done by adding a hidden field containing the value ‘false’.
Eg.
<%= Html.CheckBox("Sites", s.Selected, new { value = s.Value })%>
Produces the HTML
<input id="Sites" name="Sites" type="checkbox" value="1" /><input name="Sites" type="hidden" value="false" />
This is all good and well, until you attempt to use checkbox groups. That is more than one checkbox with the same name where the values are sent back in a single comma separated string.
MVC can split this string up for you automatically if you define the value as an array (string[] Sites).
Here’s the view code:
<% foreach(var s in Model) { %>
<li><%= Html.CheckBox("Sites", s.Selected, new { value = s.Value })%>
<label><%= s.Name %></label>
</li>
<% } %>
The appropriate controller action:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int Id, string Name, string SubmissionUrl, string[] Sites)
Unfortunately, because the Html.Checkbox produces this hidden field value as well, the resulting array contains not only values for the selected checkboxes but also ‘false’ for every un-checked checkbox. You get an array that looks something like this:
[0] 'false'
[1] 'false'
[2] '110'
[3] '50'
[4] 'false'
Where 'false' is for checkboxes that are not selected, and integers are the values for the checkboxes that are selected.
This can throw your code out quite a bit if you have only integers for the values of your checkboxes and want to define the result as an array of integers, like so:
public ActionResult Edit(int Id, string Name, string SubmissionUrl, int[] Sites)
Which results in an exception being thrown because it can’t convert the string value ‘false’ to an integer.
The solution is very simple, just avoid Html.Checkbox and manually create the checkboxes in your view code like this:
<% foreach(var s in Model) { %>
<li><input type="checkbox" name="Sites" value="<%=s.Value%>" <% if (s.Selected) { %>checked="checked"<% } %> />
<label><%= s.Name %></label>
</li>
<% } %>
Hope this helps someone else!
When all else fails, read the source code. :) this is from HtmlHelper.cs:
// Render an additional <input type="hidden".../> for checkboxes. This
// addresses scenarios where unchecked checkboxes are not sent in the request.
// Sending a hidden input makes it possible to know that the checkbox was present
// on the page when the request was submitted.
I'm not exactly sure how useful that is, but at least you know the intention.
I think I found something on the web that is directly related to my question.

Resources