I'm using HTML5 field validation for controls input type = "number" , "email". On Submit red outline for this controls are coming since its a required field. But while clearing control values I want to remove this red border also. Any pointers will be helpful. I have tried $("#txtName").removeClass('invalid'); but its not working.
$("#txtName").removeClass('invalid') would work if you have a custom CSS class (.invalid) which you added yourself upon form validation (for example, with $("#txtName").addClass('invalid')).
If you're using built-in form validation (i.e. with <input type="..." required>), you should see
the answer to this other question, specifically the setCustomValidity(error) method.
Related
I'm creating an address form for my web application and am having trouble figuring out the styling rules for HTML5 form validation with the required attribute. The examples and behavior described below are using Firefox.
The HTML for the first input field of the form looks like this:
<label for="addressLine1" class="form__label">
Address Line 1
</label>
<input type="text" required aria-required="true" class="form__input-text" id="addressLine1"/>
Without any custom styling the input behaves like this:
When the page loads, the input field displays the default styling for a text input
If I try to submit the form with the required input blank, the browser adds a red border (or shadow?) to the input
I want to retain this behavior, where the input displays some default styling on load, and only displays "invalid" styling if the user tries to submit the form with any required fields blank (or otherwise invalid). But I can't find a straight answer as to what attributes/pseudo classes I need to modify to change the styling while retaining this behavior. If I use the :invalid pseudo class, I get this behavior:
On load, the input already has my "invalid" styling, because the field is blank
If I try to submit the form with the field blank, the browser adds the red border/shadow on top of my "invalid" styling
I can only get my default/valid styling to appear by entering valid data into the input
How do you retain the default behavior (default styling on load, invalid styling on invalid submission) with custom styles, and can it be done with just CSS or do I have to add some JS functionality?
Alright so after reading over the CSS Pseudo Class docs on MDN, it doesn't look like there is any combination of pseudo classes you can string together to model the various states that make this behavior work correctly. So after playing around a bit and looking over the Bootstrap validation link Alex Schaeffer suggested, but deciding I didn't want to add extra dependencies/style sheets I didn't really need, here's the solution I came up with that adds minimal extra CSS and JavaScript.
First off, the red border was, indeed, a box shadow, so I was able to override that just by adding this to my (S)CSS:
.form__input-text {
/* default input styling goes here */
box-shadow: none;
}
Next, I added a bit of state to my component to keep track of whether or not the form has been validated yet. I'm using Svelte, so this was as simple as adding a boolean variable inside the component's <script> tag like so:
let wasValidated = false;
Then I added a conditional class to my HTML/JSX. If you're using another framework or jQuery/vanilla JS, you might need to explicitly do this with a function wired to an event handler, but in Svelte I just need to change my markup to this:
<label for="addressLine1" class="form__label">
Address Line 1
</label>
<input
type="text"
required aria-required="true"
class="form__input-text"
class:wasValidated="{wasValidated}"
id="addressLine1"
/>
All the class:wasValidated="{wasValidated}" bit is doing is conditionally adding a .wasValidated class to that input element if/when the wasValidated variable is truthy.
Then, back in my (S)CSS I added the following to apply my "invalid" styling (which at this point just changes to border color to a shade of red) only when the form had been validated at least once, and only to invalid elements:
input.wasValidated:invalid {
border-color: $red;
}
Then I wired a simple onClick function to the submit button that changes the wasValidated variable to true when the button is clicked:
HTML/JSX
<button on:click|preventDefault={onClick} class="form__submit-button" type="submit">
Search
</button>
JS
const onClick = e => {
wasValidated = true;
};
The function needs to be wired to a click event and not a submit event, because the submit event is never triggered if the form fails validation.
So now, when the page first loads, all the form inputs display the default styling, regardless of validity, because wasValidated is set to false. Then, when the submit button is clicked wasValidated is toggled to true, the .wasValidated class is applied to any required elements, which, if they are invalid, then display the "invalid" styling. Otherwise, if the form is successfully submitted, the onSubmit function wired to the form handles things from there.
Edit: As it turns out, in Svelte, you can unbind event handlers after the first time the event fires. So my markup for the submit button now looks like this:
<button on:click|preventDefault|once={onClick} class="form__submit-button" type="submit">
Search
</button>
Adding the |once modifier to on:click unbinds the onClick function the first time the button is clicked, so the function doesn't keep firing unnecessarily if the user attempts to submit invalid data multiple times.
How do you retain the default behavior (default styling on load,
invalid styling on invalid submission) with custom styles, and can it
be done with just CSS or do I have to add some JS functionality?
You can achieve this effect with a very small amount of javascript (four lines).
The reason why your input is showing as invalid is because it is both empty and required.
So one 3-step approach looks like this:
Step 1: Declare the element in your HTML using the attribute required
<input type="text" required>
Step 2: Then remove that attribute via javascript immediately
const addressLine1Input = document.getElementById('addressLine1');
addressLine1Input.removeAttribute('required');
Step 3: Then, as soon as a single character is entered into the <input> use javascript a second time to add the required attribute back in again.
const setRequired = (e) => e.target.required = 'required';
addressLine1Input.addEventListener('keyup', setRequired, false);
You can test that all this is working below by adding one or several characters to the <input> and then deleting all of them.
You will see that the <input> is initially empty but does not show as invalid, then contains characters and does not show as invalid and, finally, is empty again and now does show as invalid.
Working Example:
const addressLine1Input = document.getElementById('addressLine1');
addressLine1Input.removeAttribute('required');
const setRequired = (e) => e.target.required = 'required';
addressLine1Input.addEventListener('keyup', setRequired, false);
input:invalid {
background-color: rgba(255, 0, 0, 0.3);
border: 2px solid rgba(255, 0, 0, 0.5);
}
<form>
<label for="addressLine1" class="form__label">Address Line 1</label>
<input type="text" name="addressLine1" id="addressLine1" class="form__input-text" placeholder="Enter address here..." aria-required="true" required>
</form>
I don't think that this is possible with pure CSS, you also need some JavaScript
CSS
#addressLine1{
border: none;
background: none;
outline: none;
border-bottom: 1px solid black;
}
JS
document.getElementById('form_id').addEventListener('submit',function(e){
let address = document.getElementById('addressLine1').value
if(address == ""){
e.preventDefault()
address.style.borderBottomColor = "red";
}else{
address.style.borderBottomColor = "black";
}
})
The easiest way to accomplish unified styling across all browsers would be to use Bootstrap Validation https://getbootstrap.com/docs/4.0/components/forms/?#validation.
In my AngularJS project I have an account details page where you can change your personal account information. This page allows for multiple phone numbers and e-mailaddresses to be supplied. Using mouse input (or tabbing to buttons and pressing them with space bar) works perfectly, however I'd like to add the convenience of the enter key pressing the 'logical' buttons.
My form looks like (accidentally forgot to translate a few items):
A simplified version of the HTML for the form can be found on PasteBin, I've mainly removed the directives for managing the lists.
All buttons are <button> elements except for the cancel button which an <a> to the previous page, and the submit button is <button type="submit">.
When selecting any text box and pressing enter, the first (non-disabled) <button> element is 'clicked'. Meaning if I would change the last name, hit enter, the first phone number would be removed.
When you're in a new entry of phone numbers or e-mailaddresses (the row with the green + button) it should click that button, and if it's disabled do nothing.
When you're in any other text box on the form it should hit the save button, and also if the save button's disabled, do nothing.
Both buttons will be disabled based on form validation.
There'd be no trouble in changing the type of a button from button to submit if that'd help.
I would preferably have an all HTML solution, using just semantics, but I doubt that's really possible. So the logical alternative would be to use an AngularJS directive.
Please do not provide a jQuery or plain JavaScript solution relying on IDs or something like that. I don't want to hack my way around AngularJS, rather embrace it.
In the meantime I've worked on a directive that allows me to declare what I've called 'submit scopes'.
In essence you have actions (inputs) and targets (buttons), they're bound through a service by a key you can assign in the template. To avoid keys from clashing and from simple annoying work you can create a submit-scope which will cause it's children to prepend a unique key to the value they're accessing.
Within a submit-scope you can still override an action to use a global key instead by setting the attribute global-submit="true".
Example code:
<div submit-scope>
<input type="text" submit-action />
<button type="button" submit-target>Pressing enter in the above field will click this button.</button>
</div>
You can view the entire source code and a slightly larger example on Plnkr.
I just tried to replace
<button>Cancel</button>
with
<input type="button" value="Cancel">
and it seems to work correctly...
I have a Employee entity that I'm binding to an "Edit" view in an MVC3/Razor application. The Employee entity has a property for OccupationTypeId. OccupationTypeId points to the OccupationType table which contains several lookup values. The natural choice would be to use #Html.DropDownListFor to render a <select> tag containing a list of Occupations.
The OccupationType table schema is fairly standard: Id, Name, Description, IsEnabled. Since OccupationTypes can be disabled, I want the OccupationTypeId drop down to still render disabled options so the user can always see their selection if it's disabled, but a disabled option can't be selected by the user. In other words, a user can't change an existing OccupationTypeId to a disabled option.
I thought about creating a #Html extension method to build my <select> tag with the options and simply tack on a disabled attribute to disabled options. I think that would be straight forward...
However, disabled selected options don't seem to post back to the controller method. In other words, Employee.OccupationTypeId would be null when I post to Edit.
Is there any way to change this behavior or is this built in to MVC 3? I thought about using hidden fields, but what if OccupationTypeId is required and I have validation enabled?
Has anyone else faced this?
Thanks
You could have a hidden field that gets updated when the change event occurs in the dropdown list. This way the OccupationTypeId field is always passed.
<input name='CurrentOccupationId' type='hidden' value='#Model.Employee.OccupationTypeId' />
<script>
$(function() {
$('#dropDownId').change(function() {
$('input[name="CurrentOccupationTypeId"]').val($(this).val());
});
});
</script>
Is there any way to change this behavior or is this built in to MVC 3?
I thought about using hidden fields, but what if OccupationTypeId is
required and I have validation enabled?
It has nothing to do with MVC 3 in particular; all disabled html elements don't post back in general.
The solution I've used is to "simulate" the disable element by styling the appropriate element with CSS. You can, for example, set the element's background (or foreground) color to gray and set the readonly attribute (when it makes sense) instead.
See this similar thread.
What is it called or where can I find code for placing a 'suggestion' or grayed out text in a form field box that doesn't get pass as a value. I know i can prepopulate it, but want to use it to only provide guidance. Example, box that says " "
The terminology you're referring to is called a watermark.
There are many existing Javascript solutions written for this already, like this one.
JavaScript will do this. I've used the jQuery framework, for example:
Setting the value:
$('#comment_box').val('Optional comment..');
On click, removing the value:
$('#comment_box').val('');
On submit:
if (comment == 'Optional comment..'){
comment = '';
}
And submit your comment. I've left out the functions here but you can get an idea.
HTML5 has a placeholder attribute supported by many modern browsers.
(But alas not MSIE.)
The above-linked article explains how to test for support and implement a javascript fallback.
use
<input type=text disabled value='...'/>
(disabled wont pass the values, whereas readonly will pass the value)
I think what you are referring to is a watermark
http://www.asp.net/ajax/ajaxcontroltoolkit/Samples/TextBoxWatermark/TextBoxWatermark.aspx
or
there are jquery defaultvalue plugins
I have a bunch of optional "write-in" values for a survey I'm working on.
These are basically a radio button with a textbox within the answer field - the idea being that you would toggle the button and write something into the box.
What I'd like to do is have the radio button toggled whenever a user clicks in the text field - this seems like a use-case that makes a lot of sense.
Doing this:
<input type="radio" id="radiobutton"><label for="radiobutton">Other: <input type="text" id="radiobutton_other"></label>
works fine in Chrome (and I am guessing, other WebKit browsers as well), but there are weird selection issues in Firefox, so I'm assuming its a non-standard practice that I should stay away from.
Is there a way to replicate this functionality without using JavaScript? I have an onclick function that will work, but we're trying to make our site usable for people who might have NoScript-type stuff running.
Putting an input inside a label actually has a slightly different meaning. It doesn't make the input itself a label, it implicitly associates the label with the input in the same way as if they were linked by a for/id.
However, this only happens when the label doesn't already have a for attribute to override that (see HTML4 s17.9: “When present, the value of this attribute must be the same as the value of the id attribute of some other control in the same document. When absent, the label being defined is associated with the element's contents.”). It is unclear according to spec what should happen when both containment and for are present.
(And also it doesn't work in IE, which makes the point moot in practical terms.)
No, you'll need some scripting for this.
<input type="radio" id="radiobutton">
<label for="radiobutton_other">Other:</label>
<input type="text" id="radiobutton_other">
<script type="text/javascript">
var other= document.getElementById('radiobutton_other');
other.onchange=other.onkeyup= function() {
if (this.value!=='')
document.getElementById('radiobutton').checked= true;
};
</script>
It (an input inside a label) validates just fine as HTML 4.01. One potential issue I can see with your code is that both radio elements have the same ID in your example. Element IDs must be unique in HTML and XHTML documents and you should use the name attribute instead to identify a radio group.
If you are still having trouble after changing this, you will have to move the input outside of the <label> element and use scripting.