I am working on this little project with an online order service for pizzas.
(using Spring Web MVC, Thymeleaf, ...)
Yesterday, someone helped me out adding inputs for selecting an specific amount and size.
<div>
<form th:action="#{/saveOrderAndReload(name=${pizza.name})}" method="post">
<div class="input-group">
<span class="input-group-addon">Bestellmenge (min. 1, max. 10):</span>
<input type="number" name="amount" class="form-control" min="1" max="10" placeholder="1"/>
</div>
<div class="input-group">
<input type="radio" name="size" value="1"> Klein</input>
<input type="radio" name="size" value="2"> Mittel</input>
<input type="radio" name="size" value="3"> Gross</input>
</div>
<div class="form-group">
<div class="form-group">
<input type="submit" class="btn btn-primary btn-success" value="zur Bestellung hinzufuegen"/>
</div>
</div>
</form>
The "amount" field protects the application itself from false input because it only allows integers from 1-10, otherwise the User gets a notification asking for an numeric input.
The radio input where you can select between 3 sizes has 2 problems:
1) The buttons arent among themselfes, they are next to each other.
2) I dont know how to prevent the user from doing no input.
I looked around for quite some time finding the standart html version for this:
<form>
<input type="radio" name="gender" value="male" checked> Male<br>
<input type="radio" name="gender" value="female"> Female<br>
<input type="radio" name="gender" value="other"> Other
</form>
And something like this:
<ul>
<li th:each="ty : ${allTypes}">
<input type="radio" th:field="*{type}" th:value="${ty}" />
<label th:for="${#ids.prev('type')}" th:text="#{${'seedstarter.type.' + ty}}">Wireframe</label>
</li>
</ul>
We didnt learn anything about the second one so I decided to use the standart html. But I does not want to work like that example: It gets errors that this "checked" expression is not allowed, " tag is not closed" and whatnot.
So my questions are:
1) What can I do to make the input look better?
2) How can I set like a placeholder or standart value so the application always gets this input and does not crash?
As you might have realized I am a complete beginner with this type of stuff so be lenient ;)
Answer 1
If you want the change the way the radio buttons are looking, this might help: http://code.stephenmorley.org/html-and-css/styling-checkboxes-and-radio-buttons/.
Some notes and Answer 2
It gets errors that this "checked" expression is not allowed, " tag is
not closed" and whatnot.
Thymeleaf dies not allow attribute minimization. That means that you need to provide a value for each attribute. You just have to use checked="checked" instead of checked.
<form method="post">
<!-- Make sure to always set a value for attributes when using thymeleaf (use checked="checked" instead of checked) -->
<div><input type="radio" name="gender" value="male" checked="checked" />Male</div>
<div><input type="radio" name="gender" value="female" />Female</div>
<div><input type="radio" name="gender" value="other" />Other</div>
</form>
This is actually wrong:
The "amount" field protects the application itself from false input
because it only allows integers from 1-10, otherwise the User gets a
notification asking for an numeric input.
You are only validating on the client side. Clientside validation is okay if you want to give your users feedback even before they submit your form but it is not enough to protect yourself from bad input.
Nathan Long does explain why client side validation is not enough pretty well (JavaScript: client-side vs. server-side validation):
It is very dangerous to trust your UI. Not only can they abuse your
UI, but they may not be using your UI at all, or even a browser. What
if the user manually edits the URL, or runs their own Javascript, or
tweaks their HTTP requests with another tool? What if they send custom
HTTP requests from curl or from a script, for example?
As you are using spring-mvc you should take adventage of it and take a look at the following tutorial: https://spring.io/guides/gs/validating-form-input/.
To provide default values when working with spring-mvc you can just give the field a value:
public class PersonForm {
// this field will have a default value (foo)
// NotNull will ensure that a value is set for this field when validated by spring (however it can be an empty string... take a look at hibernates #NotBlank annotation if you want to prevent empty string or use a regex)
#NotNull
private String gender = "foo";
}
However default values often dont make sense for input[type="text"]. If you want to prodive a placeholder for any input you could just use the html attribute placeholder="the placeholder":
<input type="text" name="name" value="" placeholder="Enter your name" />
Related
I work on a large Backbone application at work. The interface is essentially a big form. We use the name attribute to map our inputs to our model properties so we can autosave each field on change or enter, letting Backbone do its thing. I just spent two days trying to figure out why one particular section causes the page to reload with a weird URL. The answer is obvious now, but after building a big app over 9 months, you tend to overlook the small things.
Throughout the application we use <input> all over the place without a wrapping <form>. In one case, however, we have a repeating element in the form of a Handlebars template that contains radio buttons with the same name:
<div id="1">
<input type="radio" name="choose" value="yes"> Yes
<input type="radio" name="choose" value="no"> No
<input type="text">
</div>
<div id="2">
<input type="radio" name="choose" value="yes"> Yes
<input type="radio" name="choose" value="no"> No
<input type="text">
</div>
<div id="3">
<input type="radio" name="choose" value="yes"> Yes
<input type="radio" name="choose" value="no"> No
<input type="text">
</div>
The problem with this is that they get grouped together because of they all have the same name attribute. So, instead of getting 3 values (one for each group), we were getting 1 value (for one big group).
Since we know that radio button groups are "scoped" to the containing <form>, we just wrapped it:
<div id="1">
<form>
<input type="radio" name="choose" value="yes"> Yes
<input type="radio" name="choose" value="no"> No
<input type="text">
</form>
</div>
<div id="2">
<form>
<input type="radio" name="choose" value="yes"> Yes
<input type="radio" name="choose" value="no"> No
<input type="text">
</form>
</div>
<div id="3">
<form>
<input type="radio" name="choose" value="yes"> Yes
<input type="radio" name="choose" value="no"> No
<input type="text">
</form>
</div>
This works just fine for the radio buttons, but now that we have a form, hitting enter on the text <input> actually submits the form, instead of autosaving (technically, in addition to autosaving). At the time, this never even occurred to me, since we somehow managed to avoid this everywhere else in the application.
I can think of a few different solutions to this problem: setting a submit handler on the form, setting a submit handler on the text input, leaving the text input outside the form. But these seem like hacks to deal with what I would say is broken behavior. If input elements work outside of forms, then grouping input elements should work outside of forms. And since we're already using the name attribute (which works for everything else), unique names isn't really an option.
So is there a best practice for situations like this? Is there an element other than <form> that will properly scope radio buttons? Am I just going to have to live with <form onsubmit="return false;">?
P.S. We support IE 8+
UPDATE
This is what I ended up with:
<div id="1">
<form onsubmit="return false;">
<input type="radio" name="choose" value="yes"> Yes
<input type="radio" name="choose" value="no"> No
</form>
<input type="text">
</div>
Best thing to do would be to change the names of each group to be unique.
Second best would be to group them by form like you have done, and add the return false.
Third best would be to block form submission using jquery 'preventdefault' (which could work for all forms given a particular id).
Last (and the most ridiculous option) would be to send each group of buttons to it's own small html file and use iframes to display them on the same page.
I need to send a very long form with lots of checkboxes. They're grouped by areas, like this:
<fieldset>
<legend>Whatever1</legend>
<div class="checkbox-list">
<label class="checkbox inline"><input type="checkbox" name="Hobbies" value="Arts"> Arts</label>
<label class="checkbox inline"><input type="checkbox" name="Hobbies" value="Bars"> Bars</label>
<label class="checkbox inline"><input type="checkbox" name="Hobbies" value="Books"> Books</label>
(more items)
</div>
</fieldset>
<fieldset>
<legend>Whatever2</legend>
<div class="checkbox-list">
<label class="checkbox inline"><input type="checkbox" name="Interests" value="Architecture"> Architecture</label>
<label class="checkbox inline"><input type="checkbox" name="Interests" value="Audio"> Audio/vídeo</label>
<label class="checkbox inline"><input type="checkbox" name="Interests" value="Business"> Business</label>
(more items)
</div>
</fieldset>
The form is much longer, but you get the idea.
Using name="Hobbies" value="Arts" my django backend receives all the checkboxes grouped in a Hobbies array, which is very convenient, but I need to know the unchecked checkboxes, too. I know about the hidden input trick, but it's not useful to me, because I use the value field as part of the checkbox grouping.
Any idea about what can I do?
Well, as I guess you already know, there is fundamentally no way of asking the browser which boxes were left unticked. Blame the inventors of HTML forms...
Here are a few simple approaches which don't break your grouping logic:
Re-generate the list of checkboxes which you displayed on your server side. This is preferable in a lot of cases anyway, since it means you're not trusting the data coming back to be exactly what you displayed. (Consider what happens if I use a debugging tool like Firebug to delete one of your checkboxes, or add a new one...)
Include hidden inputs with a corresponding name for each checkbox - "Interests_All", "Hobbies_All", etc - so that you have two arrays of data, one including just the checked items, one including everything displayed.
Use radio buttons instead of check-boxes. Yes, they display differently, but they can have the functionality you want of submitting a Yes/No value, rather than just adding to the array or not.
How about setting a default false value for each checkbox in the backend. If a value has been passed by the browser, you can then change the value to true.
You could add a hidden input field, and on form submit, use jQuery to populate the value of the hidden input with an array containing the values of the unchecked checkboxes:
$("form").on("submit", function(e) {
e.preventDefault();
// Create an array of unchecked Hobbies
var uncheckedValues = [];
$(this).find("input[name='Hobbies']:not(:checked)").each(function() {
uncheckedValues.push(this.value);
});
// Set the uncheckedValues array as hidden input value
$("#your-hidden-input").val(uncheckedValues);
alert($("#your-hidden-input").val());
// Handle the form submission
handleFormSubmit();
});
See DEMO.
I've solved it. The idea was in IMSoP's answer. Here's my solution, maybe it can help someone:
<fieldset>
<legend>Whatever1</legend>
<div class="checkbox-list">
<input type="hidden" name="Hobbies_Arts">
<label class="checkbox inline"><input type="checkbox" name="Hobbies" value="Arts"> Arts</label>
<input type="hidden" name="Hobbies_Bars">
<label class="checkbox inline"><input type="checkbox" name="Hobbies" value="Bars"> Bars</label>
<input type="hidden" name="Hobbies_Books">
<label class="checkbox inline"><input type="checkbox" name="Hobbies" value="Books"> Books</label>
(more items)
</div>
</fieldset>
With that, is very easy to handle the lists in the django side.
Suppose this checkbox snippet:
<input type="checkbox" value="1">Is it worth?</input>
Is there any reason to statically define the value attribute of checkboxes in HTML? What does it mean?
I hope I understand your question right.
The value attribute defines a value which is sent by a POST request (i.e. You have an HTML form submitted to a server).
Now the server gets the name (if defined) and the value.
<form method="post" action="urlofserver">
<input type="checkbox" name="mycheckbox" value="1">Is it worth?</input>
</form>
The server would receive mycheckbox with the value of 1.
in PHP, this POST variable is stored in an array as $_POST['mycheckbox'] which contains 1.
I just wanted to make a comment on Adriano Silva's comment.
In order to get what he describes to work you have to add "[]" at the end of the name attribute, so if we take his example the correct syntax should be:
<input type = "checkbox" name="BrandID[]" value="1">Ford</input>
<input type = "checkbox" name="BrandID[]" value="2">GM</input>
<input type="checkbox" name="BrandId[]" value="3">Volkswagen</input>
Then you use something like: $test = $_POST['BrandID']; (Mind no need for [] after BrandID in the php code).
Which will give you an array of values, the values in the array are the checkboxes that are ticked's values.
Hope this helps! :)
One reason is to use the ease of working with values in the system.
<input type="checkbox" name="BrandId" value="1">Ford</input>
<input type="checkbox" name="BrandId" value="2">GM</input>
<input type="checkbox" name="BrandId" value="3">Volkswagen</input>
When the form is submitted, the data in the value attribute is used as the value of the form input if the checkbox is checked. The default value is "on".
$('form').on('change', update).trigger('change')
function update() {
var form = $(this)
form.find('output').text('→ ' + form.serialize())
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<input type="checkbox" name="foo">
<output></output>
</form>
<form>
<input type="checkbox" name="foo" checked>
<output></output>
</form>
<form>
<input type="checkbox" name="foo" value="1" checked>
<output></output>
</form>
<form>
<input type="checkbox" name="foo" value="bananas" checked>
<output></output>
</form>
For the sake of a quick glance answer, from MDN
when a form is submitted, only checkboxes which are currently checked are submitted to the server, and the reported value is the value of the value attribute
It can be confusing because seeing something like
<input type='checkbox' name='activated' value='1'> might lead one to believe that the 1 means true and it will be treated as though it is checked, which is false. The checked attribute itself also only determines if the checkbox should be checked by default on page load, not whether it is currently checked and thus going to be submitted.
I remember reading in the spec once that both the id attribute and the name attribute share the same namespace and have to be unique. Henceforth I've always tried to fulfill this requirement in my applications, dreading even to give the same id and name to the same element.
But lately I've started working with ASP.NET MVC 3, and it (like PHP) can use the same name attribute on several input controls to form a collection of values at server-side. I tried to look up the relevant section in the spec - but failed to find it. Perhaps I have misunderstood something then, or read the wrong documentation?
How is it then? I want to produce as valid HTML as possible (both 4.01 and 5 in different apps). Can I use this trick without fear? Or would I be violating something and should better stick to unique values?
The name attribute is only valid on the <form> and form elements (<input>,<textarea> and <select>). It's used to specify the name to associate with the name/value pair that is submitted on a form post.
For example:
<input type="checkbox" name="foo" value="1" />
if checked will submit foo=1. In the DOM you can reference form elements from the form.elements collection by specifying the name as the index. If name is not unique, the collection returns an array of elements rather than the element. Modern DOM's support looking up form elements by name as:
document.getElementsByName(nameValue)
note: it always returns an array even if only one element is found.
id attribute is from the XML world, and is a unique id for any node, not just form elements. Unlike the name attribute it is valid on any HTML node. Also like the name attribute, it must follow the valid identifier rules. The identifier should start with an alpha, and only contain alpha ([a-zA-Z]), numbers, hyphen, underscore and colons (note ASP.NET breaks this rule by starting reserved IDs with a underscore - thus they will always fail an HTML/XML lint - actually some proxies strip them). To find any HTML element by id you use:
document.getElementById(idvalue)
this only returns one DOM node.
The name attribute is not unique. For instance, it is used to group radio buttons. It represents the value of a particular form property. ids must be unique.
ID should be unique but you can use multiple form elements with the same NAME. This is standard for how radio buttons work so you can force one seletion of a radio button group.
Must names be unique between forms for radio input groups?
I understood that name didn't have to be unique because radio elements can share the same name, but nobody said whether or not groups of radio elements in different forms would interfere with each other or not. So I created this simple example below to test. In my browser, I can pick 2 of the 6 radios in the example below, and there are two forms. So it appears that putting them in separate forms will isolate them.
<form>
<input type="radio" name="test" value="1">
<input type="radio" name="test" value="2">
<input type="radio" name="test" value="3">
</form>
<form>
<input type="radio" name="test" value="a">
<input type="radio" name="test" value="b">
<input type="radio" name="test" value="c">
</form>
I also wondered if the same behavior would hold true with the newer <fieldset> element, however it doesn't seem to. I guess that makes sense because if I sent the form it would need to format the data to accommodate the name conflict somehow. I can only pick 1 among the 6 radios here:
<form>
<fieldset name="test1">
<legend>test1</legend>
<input type="radio" name="test" value="1">
<input type="radio" name="test" value="2">
<input type="radio" name="test" value="3">
</fieldset>
<fieldset name="test2">
<legend>test2</legend>
<input type="radio" name="test" value="a">
<input type="radio" name="test" value="b">
<input type="radio" name="test" value="c">
</fieldset>
</form>
I'm not sure why anyone would want to do this, but you can also associate each element with a different form by using the form=<form id> attribute. It seems to separate the radio groups again. As shown here:
<form id="a">
</form>
<form id="b">
</form>
<fieldset name="test1">
<legend>test1</legend>
<input form="a" type="radio" name="test" value="1">
<input form="a" type="radio" name="test" value="2">
<input form="a" type="radio" name="test" value="3">
</fieldset>
<fieldset name="test2">
<legend>test2</legend>
<input form="b" type="radio" name="test" value="a">
<input form="b" type="radio" name="test" value="b">
<input form="b" type="radio" name="test" value="c">
</fieldset>
I think ideally a fieldset would create some sort of grouping that was more than just visual, but it doesn't oh well. At least radio groups can be separated by forms.
Addendum: What does the form data look like when you use the same name within two or more fieldsets inside of one form? Let's see.
My suspicions are confirmed. There's just one 'test' parameter and fieldsets have no effect on the data at all. Try picking a radio and hitting submit.
function examine(e){
e.preventDefault()
e.stopPropagation()
var formData = new FormData(e.target)
,formProps = Object.fromEntries(formData)
document.getElementById('out').innerText = JSON.stringify(formProps,null,2)
return false;
}
document.getElementById('mainform').addEventListener('submit',examine)
<form id="mainform">
<fieldset name="test1">
<legend>test1</legend>
<input type="radio" name="test" value="1">
<input type="radio" name="test" value="2">
<input type="radio" name="test" value="3">
</fieldset>
<fieldset name="test2">
<legend>test2</legend>
<input type="radio" name="test" value="a">
<input type="radio" name="test" value="b">
<input type="radio" name="test" value="c">
</fieldset>
<button type="submit">examine</button>
</form>
<pre id="out"></pre>
On form submission, how could you possibly mark a checkbox/radiobutton as required?
Source of inspiration: Pekka's answer to a question
Required checkboxes are not unusual. Practically every registration form uses some form of the "I have read and accept the User Agreement" checkbox.
If you have Opera handy try out the code below. The form won't submit unless the checkbox is checked.
<!doctype html>
<html>
<head>
<title>html5</title>
</head>
<body>
<h1>html5 test</h1>
<form action="/">
<input type="checkbox" required="required" id="cb" name="cb">
<label for="cb">required checkbox</label>
<input type="submit">
</form>
</body>
</html>
For checkboxes, the best way is probably to pre-select it and set it to disabled. Just kidding.
To ensure one radio button in a group has been selected, either start with a default choice or validate using javascript. There are no HTML-ways to do that because every possible selection is valid.
In html5 there is a required attribute for checkboxes.
They are somehow weird, so let me quote something to explain how they work.
For checkboxes, the required attribute shall only be satisfied when one or more of the checkboxes with that name in that form are checked.
For radio buttons, the required attribute shall only be satisfied when exactly one of the radio buttons in that radio group is checked.
Of course you always have to validate server side because the client can always send you whatever he desires. Just use these methods for better user experience.
I tested required attribute for Radio Buttons today on Firefox 17.0.1 on XP SP2.
It seems to comply with the specification of required attribute for radio buttons/groups. As Firefox prompts "Please select one of these options." for both of the code snippets below:
Either you set required attribute for each of the radio buttons
<input type="radio" name="gender" value="male" required="required" />
<input type="radio" name="gender" value="female" required="required" />
Or Any One of the Radio elements
<input type="radio" name="color" value="blue" />
<input type="radio" name="color" value="red" required="required" />
<input type="radio" name="color" value="green" />
Any comments and updates are welcome.
I just tried it on a radio button in Firefox 4. Adding required to one radio input, then submitting before selecting one, triggers a "Please select one of these options" tooltip.
E.g. this works:
<input type="radio" name="gender" value="m" required />
<input type="radio" name="gender" value="f" />