I am using Knockout to validate my page, and everything is working correctly. On input blur, if the required field is empty, the error symbol * is displayed next to the text box. However, I have a span tag at the bottom of the page that I want to display * Required field if and only if a field has the * next to it.
My intention was to have the span similar to
<span data-bind="visible: errors().length > 0"> * Required field </span>
The issue is, apparently on page load, the .length of my errors variable from
errors = ko.validation.group({ variables })
evaluates to all my inputs as having errors since they are null or empty on page load. Is there any way to disable this initial validation, but still have it validate on blur? Request any code if necessary, but I did not see that as pertinent at the moment.
errors() contains all the error messages of your validation group.
Try this:
showRequiredMessage = function() {
for (i = 0; i < errors().length; i++) {
if (errors()[i].indexOf("*") > -1 ) {
return true;
}
}
return false;
}
It checks if any of the error messages contain the *.
<span data-bind="visible: showRequiredMessage()"> * Required field </span>
This is javascript only solution. You can use jQuery too if you prefer.
Edit.
Are you creating the span elements for your validation messages? If so,
Try letting the ko-validation do that for you. Example:
var koValidationOptions = {
decorateInputElement: true,
errorElementClass: 'input-error',
insertMessages: true,
errorMessageClass: 'field-error'
};
ko.applyBindingsWithValidation(model, document.getElementById("form1"), koValidationOptions);
Otherwise, if you prefer to add the span manually, you can also test if the user has 'touched' the inputs:
visible: yourProperty.isModified() && !yourProperty.isValid()
Hope it helps
Related
I have a form where e-mail is optional. To control that there is a checkbox. If that checkbox is unchecked, the e-mail textbox would be disabled and therefore not posted on submit. However, on the next page, if I have code like as shown below, it gives me an error if the e-mail textbox is disabled.
if (isset($_POST['submit']))
{
$_SESSION["email"] = $_REQUEST['YourEMail'];
....
}
To get around that problem, I progammatically enable a disabled e-mail textbox just before submitting besides setting its value to an empty string. The code for that is shown below.
document.getElementById('YourEMail').disabled = false
document.getElementById('YourEMail').value = ''
However, one annoying problem remains, which is that, if the user goes back to the original page, the e-mail textbox is enabled, since I enabled it problematically just before submitting the form. However, I want it to be disabled in that case. How, can I achieve that? Alternatively, how in the next page, I could see that e-mail box was disabled and therefore not even try to read $_REQUEST['YourEmail']?
if the field "#YourEMail" is optional you can check if exists in PHP. There is no need for enable/disable the field using JS.
if (isset($_POST['submit']))
{
if (isset($_REQUEST['YourEMail']) && !empty($_REQUEST['YourEMail'])){
$_SESSION["email"] = $_REQUEST['YourEMail'];
}
}
You can test it like this using a ternary:
(isset($_REQUEST['YourEMail']) && !empty($_REQUEST['YourEMail'])) ? $_SESSION["email"] = $_REQUEST['YourEMail'] : FALSE;
This would only set the session variable if the request variable is set.
I have server side validation messages for some of my text fields. The field 'title' is a required field server side with a '[Required]' data attribute in the class, but this only seems to get checked on a postback or form submit. I'm saving the 'title' text field on a jquery .change event, sudo code below. But I want to use my validationmessagefor to show the error message from the client side check. Not sure how to go about doing this?
html.
#Html.ValidationMessageFor(model => model.Overview.Title, "", new { #class = "text-danger" })
rendered as
<span class="field-validation-valid text-danger" data-valmsg-for="Overview.Title" data-valmsg-replace="true"></span>
If I want to do some client side checking in javascript and then use this element to display a client side error message can I do so. I'm just trying to save myself of using another hidden element. I know I would have to use
data-valmsg-for="Overview.Title"
because the other data attributes are the same for all the other text fields.
Whats the best way to do display client side error messages here if I want to check to make sure the "title" has length greater then 1?
Maybe something like -
$('#Overview_Title').change(function() {
var title = $(this).val();
if (title.length == 0) {
// show error message "title has to be a value to save"
}
else {
// do other work like save to db
}
});
You've got a few ways to do this but I'd argue that this is the easiest way:
MVC will by default bundle the jquery.validate javascript library into your page. Since you are already marking the field with the [Required] attribute, the Html.EditorFor will bind the correct attributes into your HTML for you so that validation can happen as necessary.
To make your current logic work with the smallest changes, you could add a <form> tag around your input field(s). I think you need this for the validate method to work out of the box. Then your javascript would change to something like this:
$('#Overview_Title').change(function() {
if ($(this).valid()) {
// do your stuff
}
else {
// error message displayed automatically. don't need to do anything here unless you want to
}
});
This would allow you to use the Required attribute to set your error message text and your ValidationMessageFor should display the error message without any extra effort on your part.
Check out this plunkr as a proof of concept: http://plnkr.co/edit/ip04s3dOPqI9YNKRCRDZ?p=preview
EDIT
I'm not positive I understand your follow-up question. But if you wanted to add a rule to a field dynamically, you could do something along these lines:
$( "#someinput" ).rules( "add", {
required: true,
messages: {
required: "a value is required to save changes"
}
});
You could add rules that aren't reflected server side by doing something like this. Then you could validate that input in the same way.
If you want to do 100% client side validation using jquery you can use something like this:
$('#Overview_ISBN').on('input', function() {
var input=$('#Overview_Title');
var is_name=input.val();
if(is_name){input.removeClass("invalid").addClass("valid");}
else{input.removeClass("valid").addClass("invalid");}
});
Here's the code of JSFiddle link
In the example i posted , if you start typing the ISBN and the Title is empty, you will get the error message.
Not sure in your question how you want to trigger the error so i assumed it's an entry in a different input
I've taken a bootstrap directive that watches all the input elements on a form and updates the CSS of its parent div to show validation errors in a Bootstrap way. The watch looks at the elements css class and if ng-invalid is present it adds has-error to the parent.
element.find('.form-group').each(function () {
var formGroup = $(this);
var inputs = formGroup.find('input[ng-model],textarea[ng-model],select[ng-model]');
if (inputs.length > 0) {
inputs.each(function () {
var input = $(this);
scope.$watch(function () {
return input.hasClass('ng-invalid') && (!input.hasClass('ng-pristine') || form.$submitted);
}, function (isInvalid) {
formGroup.toggleClass('has-error', isInvalid);
});
});
}
});
The original directive was taken from an answer on S.O. I think the original answer derives from this Reconcile Angular.js and Bootstrap form validation styling but someone took it and expanded on it and I can't find their answer. It also takes more code from this show validation error messages on submit in angularjs to handle preventing the form being submitted but I'm omitting that for now
The directive works fine when using synchronous validators but when I use an async validator it gets the validation states mixed up. After making the field invalid, the watch fires but input.hasClass('ng-invalid') returns false. I'm at a loss about why it might happen.
I've created a plunkr here http://plnkr.co/edit/0wUUPdZc0fYN6euvsIMl?p=preview
One thing that could possibly be done here is to use child forms for each form group and if the child forms are invalid, then the parent form itself will not be valid.
Here's an example.
http://jsbin.com/luvegecalo/1
I have a timesheet table. At the bottom of the table there is a button which allows me to add a row. Understandably, all the cells in the new row start off empty. The JavaScript uses:
txtFld.setAttribute('value', '');
to do so.
However, in some situations I want some of the new fields to show up but be disabled so I (in those situations) add in:
txtFld.setAttribute('disabled', 'disabled');
The problem is that, when doing this, after submission, when the table re-renders itself, all those empty values show up as zeroes instead of empty strings. As far as calculations go, that's fine, but I don't want rows of zeroes. I want empty cells. If I take out the disabled part, it works fine.
I've temporarily remedied this by, instead of using disabled, using readonly, which seems to give me the desired results. The only problem is that, while the text field remains non-editable, the user CAN place the cursor inside the box. I want the cleaner, "can't even click in here" that the disabled gives me.
Any thoughts on why the disabled feature is doing this and how I can use disabled without the resulting row of zeroes?
For the record, I've mixed and matched every combination of:
txtFld.setAttribute('value','');
txt.setAttribute('value', null);
txtFld.value = '';
txtFld.value = null;
with
txtFld.setAttribute('disabled');
txtFld.setAttribute('disabled', 'true');
txtFld.setAttribute('disabled', 'disabled');
txtFld.disabled = 'true';
txtFld.disabled = 'disabled';
that I can think of with the same results (or worse) every time.
Thanks.
When a field is disabled, it's not included in the form parameters sent to the server.
In new browsers (IE11+, and pretty much everything else) you can use CSS to disable pointer events on the element:
txtFld.readonly = true;
txtFld.style.pointerEvents = 'none';
That'll make the element simply not respond to any clicks. (Here is a jsfiddle.) Because it's not disabled, a form POST will send the empty field to the server.
You should disable fields by setting the "disabled" property of their DOM nodes to true (the boolean constant, not the string).
txtFld.disabled = true; // disables field
txtFld.disabled = false; // enables field
The "disabled" property is treated as a boolean, so setting it to any string value (other than the empty string) will set it to true:
txtFld.disabled = "false"; // disables field
Another thing you can do to exploit the real disabled browser behavior and have empty parameters posted to the server is to use pairs of inputs:
<input type=text name=whatever data-companion=whatever-c> <!-- visible input -->
<input type=hidden name=whatever id=whatever-c> <!-- invisible input -->
Now whenever you enable the text field, you disable the hidden input, and vice-versa. That way there's always something posted.
For a custom image selection tool I would like to create form validation based on html 5 form validation.
For example my form consists of the following elements:
<form class="cms-form" action="">
<table width="800">
<tr>
<td width="30%">Name:</td>
<td><input type="text" name="name" class="cms-input-text" maxlength="127" /></td>
</tr>
<tr>
<td>Image:</td>
<td><textarea name="icon" class="cms-input-file" data-file-resource="images" data-options="{"min":1,"max":3}">/location-to-image.png</textarea></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Next"/></td>
</tr>
</table>
</form>
I have a Javascript that changes the textarea (.cms-input-file) into some html to add images and hides the original textarea.
It looks something like this:
<textarea name="icon" class="cms-input-file" data-file-resource="images" data-options="{"min":1,"max":3}" style="display: none;">/location-to-image.png</textarea>
<ul class="cms-input-file-list">
<li class="cms-input-file-item" data-image="/location-to-image.png">
<img src="/location-to-thumb.png" alt="" class="cms-input-file-item-thumbnail"/>
<span class="cms-input-file-item-title">location to image</span>
</li>
<li class="cms-input-file-add">Add</li>
</ul>
Since I have allot of existing forms using html5 form validation I would like to validate this element using the default form validation within html5 supported browsers, but using a hopefully existing event.
I'm looking for something like this:
$('.cms-input-file').on('customValidateFunction', function () {
var options = $(this).data('options');
if($(this).find('> li.cms-input-file-item').length < options.min)
{
return [false, 'Add more images.'];
}
if($(this).find('> li.cms-input-file-item').length > options.max)
{
return [false, 'Remove some images.'];
}
return true;
});
Does anyone know if something like this is possible using default html 5 events or how would I go about adding this event to the submit event? To actually trigger the default browser validation look and feel.
-- edit --
So far I have made an attempt to get this result using a div element which hides the original element. But now I need to add a pattern to the element to match according to my options. Is this possible?
Current progress: http://jsfiddle.net/jeffreydev/YyEVu/
If I understand correctly what you need, I think you can achieve what you are trying to do using the pattern attribute of any input element.
I've created a very simple form in jsfiddle illustrating this.
The idea is that you update the value of your input with whatever data you have in your model when adding or removing images. The example, just adds one letter f per icon. Then, you can create a regex to match the expected valid results. In the example, pattern="f{1,3}" means that to be valid, the content can be "f", "ff", or "fff" but nothing else, which means that it'll only accept from one to three files to be sent.
You would be using just default html5 form validation, but you may need a bit of tweaking to get it working.
However, if you try this way, you should keep a couple of things in mind:
As explained in the specs, the patttern is compiled as a JavaScript regular expression with the global, ignoreCase, and multiline flags disabled
Setting the disabled property of your input so that the user can't change it would take it out of the form, and thus it won't be validated
Applying certain styles as *display:none" to the input element can cause errors when the validation fails and the browser tries to gain focus on the element.
I hope you this helps
You can install a submit handler on the <form>, and dispatch a custom event from there.
That will look something like this:
$('form.cms-form').on('submit', function(evt) {
var frm = $(this);
var allElements = $(this.elements);
$('#errors').empty();
var errors = [];
var arg = {
reportValidationError : function( msg ) {
errors.push(msg);
},
form : this
};
console.log("all elements: ", allElements);
allElements.trigger('customValidate', [ arg ]);
if( errors.length !== 0 ) {
showValidationErrors(errors);
return false;
}
return true;
});
Then, you can "hook" the customValidate event, and install your own logic...
$('textarea[name=icon]').on('customValidate', function(evt, reporter) {
var options = $(this).data('options');
// ... your validation here ...
// for example:
var txt = $(this).val();
if( txt.length < options.min || txt.length > options.max ) {
reporter.reportValidationError('error: "icon" min/max exceeded!');
}
})
Here's an example at jsFiddle.
Edit
You can style the error reporting, and tweak the code, to look and behave however you want it to. Here's an example.
A very good jquery plugin to validate your forms is Mike Alsup one's.
You will find it here: http://jquery.malsup.com/form/
It is documented, ajax compatible.
It can do serialization for one field or for all fields inside the form, so it is a big advantage regarding your problem you could need to handle fields validation and error logic with your forms.
You could add the blockUI plugin of the same author to enhance user's experience, and don't have to manage double submission of the form when javascript is enabled.
http://jquery.malsup.com/block/
Answer from 2022: Yes, it is possible without jQuery etc.
Most browsers support Constraint Validation API (even IE 11 according to "caniuse")
The recommended practice is to listen to input/submit events and then set validity flags on the input-box.
<form>
<input type="text" required id="answer">
<input type="submit">
</form>
Validation JS:
const nameInput = document.querySelector("#answer");
const form = document.querySelector("form");
function validate(e) {
if (nameInput.value == "42") { //correct!
nameInput.setCustomValidity(""); // empty means "no error"
}
else {
nameInput.setCustomValidity("Wrong answer!"); //show error text
e.preventDefault(); //prevent form submit
}
}
nameInput.addEventListener("input", validate);
form.addEventListener("submit", validate);
The input event fires even when the value is changed programmatically
P.S. Codepen to play with: https://codepen.io/jitbit/pen/XWYZjXO