I'm brand new to javascript and knockout. I'm working on client side validation using knockout-validation and am having some trouble. I want textboxes that require some user input to show their error messages on blur (even if the user didn't enter anything). A problem I ran into is that I don't want the error messages to show up right away. I was able to get this working but was wondering if someone had a more elegant way to do this. The pseudo code for what I do is set a textbox's value as an observable and then subscribe that to hasfocus of the textbox. Here is the sample code of the view model and the fiddle to go with it:
self.firstName = ko.observable().extend({
required: true,
notify: 'always'
});
self.firstName.focused = ko.observable();
self.firstName.focused.subscribe(function(newVal) {
if(not the first time in the function and the value hasn't changed)
{
update the value to itself;
//if this is empty then it will trigger the "required" error message
}
});
http://jsfiddle.net/sderico/qAnxw/
I want to know if there's a nicer way to implement this functionality (or any other ways that aren't too convoluted). Thanks in advance!
You just need to specify the valueUpdate option to 'blur' on in your value binding. Then knockout will also update the value of firstName on the blur event which triggers the validation:
<input type="text" runat="server" ID="FirstName"
data-bind="value: firstName, valueUpdate: 'blur'"/>
Demo JSFiddle.
Related
I have a login Form that is validated using Angular validation as follows:
HTML for Input fields:
<input id="loginName" name="loginName" type="text" class="form-control" placeholder="Username" data-ng-model="loginName" data-ng-maxlength="246" required>
<input id="password" name="password" type="password" class="form-control" placeholder="Password" data-ng-model="password" data-ng-maxlength="246" required>
'Login' button is validated against loginName and password fields using angular validation.
In Google Chrome (other browsers behave as intended) when these fields are saved (with do you want to save username and password feature) when the page is refreshed, the model for input type 'text' -> $scope.loginName gets updated with the saved value on the other hand the model for input type 'password' -> $scope.password is always empty) and according to the validation logic form is declared invalid and the 'Login' button stays disabled even though both the input fields are populated with saved information (See first attached image).
The moment a keypress or mouse click even occurs(not necessarily on the input fields but anywhere on the web page), somehow the model for password is updated and form is validated as shown in the second image attached.
I tried using autofocus, custom autofocus directives, timeouts but it doesn't seem to work as intended.
any suggestions, probably moving the cursor to the end of the text field so that the form knows that the text has been entered in the password field by the browser?
Came across this: AngularJS browser autofill workaround by using a directive
NOTE: All he answers in above solution talk about input elements value, got by either .val() or .value methods but the tricky part is both return undefined in case of password input field.
But no luck!
Thanks.
You may use
$scope.$watch('modelValue',function(newVal,oldVal){
//your code action
});
which will keep on tracking the model value. Whenever the model has value, your code inside $scope.$watch will be triggered.
As suggested by Ziv Weissman (in the comments section above) and after wasting quite a few hours on this, I have abandoned the AngularJs style validation process for the Login button and the input type password as well.
Chrome pretends it does not have a value for the field as a security measure. There's no way to hack around that. from: here
I found a potential solution to this behaviour which involves re-capturing the password value after a delay.
Just add this directive,and call the directive from the input's
Directive code
Modeule.directive('autoComplete', function ($timeout) {
return function (scope, iElement, iAttrs) {
iElement.autocomplete({
source: scope[iAttrs.uiItems],
select: function () {
$timeout(function () {
iElement.trigger('input');
}, 0);
}
});
};
});
HTML code
<input type="text" ng-model="username" auto-complete />
Or put in tl;dr code:
form.email.$setValidity('conflict', false);
is too sticky for my simple serverside validation flow.
I'm trying to get the form to show good feedback in the event that the user enters an email address already in use by another customer. I'm running AngularJS v1.2 and have this template:
<form name="form">
<input name="email" type="email" ng-model="..." required>
</form>
<div ng-messages="form.email.$error">
<div ng-message="conflict">Email address already in use.</div>
</div>
In my controller, I'll handle the submit event and trigger the validation in my $http.post().error handler like this:
$http.post('api/form/submit/path/here').error(function(resp) {
if (resp.details === 'conflict')
$scope.form.email.$setValidity('conflict', false);
});
The problem is that when the user goes back and changes the value in the input field, the error message doesn't go away. It sticks around until I manually call $scope.form.setValidity();.
The docs say implement a custom directive with an ng-model dependency, but that seems super overkill for my purposes. I've also tried setting $scope.form.email.$valid = false; and $scope.form.email.$invalid = true; but those don't change the appearance of the textbox.
Nothing in your code modifies the conflict validation key, except for when $setValidity('conflict', false) is explicitly called. Since that is the only code setting the state of the conflict validation key and there is nothing else resetting it to true, it's expected behaviour that editing the textbox wouldn't reset its conflict validation state.
To get the behaviour that you want, you need to code for it. One way is to use ng-change.
<input name="email" type="email" ng-model="..." required ng-change="resetConflictState()">
$scope.resetConflictState = function() {
$scope.form.email.$setValidity('conflict', true);
}
I want to implement an uncommon functionality and I thought jquery validate plugin would be the best way to do it (if you suggest and answer without the plugin, it will be welcomed as well). I want to hide the form as soon as the user enters the correct word on the input field.
I tried this:
$("#beta_form").validate({
onsubmit: false,
onkeyup: true,
rules: {
beta_password: "1789"
},
success: function(){
$("#beta_form").addClass("hidden");
}
});
So, as soon as the user enters "1789" (without having to hit submit), the form is supposed to hide.
I get this error:
TypeError: settings[eventType].call is not a function
I have done it without using validate plugin
HTML :
<form id="formid">
<input type="text" id="password" ></input>
<input type="submit"></input>
</form>
Jquery :
$("#password").keyup(function(e){
if($(this).val() ==='1789'){
$("#formid").hide();
}
});
Working Fiddle
This is not a valid setting...
onkeyup: true
As per documentation,
onkeyup
Type: Boolean or Function()
Validate elements on keyup. As long as the field is not marked as
invalid, nothing happens. Otherwise, all rules are checked on each keyup
event. Set to false to disable. Set to a Function to decide for
yourself when to run validation.
A boolean true is not a valid value.
In other words, validation on every keyup event is already the default behavior so you must not set this option to true. You can only set this option to false (to disable) or to a function (to over-ride). Leave the option out to keep the default behavior.
I know you can disable the autocomplete on a form by setting autocomplete="off" on the form itself.
The problem I have is, I want to prevent the browser from populating the password field but do not want to disable username or other fields.
The other thing to consider is legacy data. Using autocomplete="off" on the form (or even the field itself) does not prevent existing users with saved passwords from getting a free-pass. Or ones that use web inspector, change the value of autocomplete and submit, allowing themselves to save the password.
I know it is possible to change the password field name attribute to a random/new one on every visit. Regretfully, I am working with a java/spring back-end and I am being told this is NOT easily manageable without a huge refactor/override.
How would you architect this? How would you enforce that the field always starts empty? There is no consistent way for browsers to event notify you of pre-population by a password manager - some may fire an onChange, others may not.
I guess I can move fields around with javascript and build the real form on the fly and submit it but once again, this will have implications with spring security and validations etc. Any other ideas?
you can made a temp variable when onFocus is call to set a variable to true ( like userFocus )
and on the onChange attribut but a short code for reseting "value" to NULL if userFocus== false) kind of overkilling imo but migth work
EDIT
function reset()
{
if (document.getElementById("hidden").value!=" ")
{
document.getElementById("demo").value=" ";
}
else;
}
function getfocus()
{
document.getElementById("hidden").value=" ";
}
else;
}
<input type="password" id="pwd" onchange="reset()" onfocus="getfocus()"/>
<input type="hidden" id="hidden" value="not focus"/>
I had to find this solution for IE 11 (since it ignores the autocomplete attribute). It works fine in other browsers. Really more of a work around, but it works.
https://stackoverflow.com/a/20809203/1248536
I was recently faced with this problem, and with no simple solution since my fields can be prepopulated, I wanted to share an elegant hack I came up with by setting password type in the ready event.
Don't declare your input field as type password when creating it, but add a ready event listener to add it for you:
function createSecretTextInput(name,parent){
var createInput = document.createElement("input");
createInput.setAttribute('name', name);
createInput.setAttribute('class', 'secretText');
createInput.setAttribute('id', name+'SecretText');
createInput.setAttribute('value', 'test1234');
if(parent==null)
document.body.appendChild(createInput);
else
document.getElementById(parent).appendChild(createInput);
$(function(){
document.getElementById(name+'SecretText').setAttribute('type', 'password');
});
};
createSecretTextInput('name', null);
http://jsfiddle.net/N9F4L/
I have a form setup with dojo 1.5. I am using a dijit.form.ComboBox and a dijit.form.TextBox
The Combobox has values like "car","bike","motorcycle" and the textbox is meant to be an adjective to the Combobox.
So it doesn't matter what is in the Combobox but if the ComboBox does have a value then something MUST be filled in the TextBox. Optionally, if nothing is in the ComboBox, then nothing can be in the TextBox and that is just fine. In fact if something isn't in the Combobox then nothing MUST be in the text box.
In regular coding I would just use an onBlur event on the text box to go to a function that checks to see if the ComboBox has a value. I see in dojo that this doesn't work... Code example is below...
Vehicle:
<input dojoType="dijit.form.ComboBox"
store="xvarStore"
value=""
searchAttr="name"
name="vehicle_1"
id="vehicle_1"
/>
Descriptor:
<input type="text"
dojoType="dijit.form.TextBox"
value=""
class=lighttext
style="width:350px;height:19px"
id="filter_value_1"
name="filter_value_1"
/>
My initial attempt was to add an onBlur within the Descriptor's <input> tag but discovered that that doesn't work.
How does Dojo handle this? Is it via a dojo.connect parameter? Even though in the example above the combobox has an id of "vehicle_1" and the text box has an id of "filter_value_1", there can be numerous comboboxes and textboxes numbering sequentially upward. (vehicle_2, vehicle_3, etc)
Any advice or links to resources would be greatly appreciated.
To add the onBlur event you should use dojo.connect():
dojo.connect(dojo.byId("vehicle_1"), "onBlur", function() { /* do something */ });
If you have multiple inputs that you need to connect this to, consider adding a custom class for those that need to blur and using dojo.query to connect to all of them:
Vehicle:
<input dojoType="dijit.form.ComboBox"
store="xvarStore"
class="blurEvent"
value=""
searchAttr="name"
name="vehicle_1"
id="vehicle_1"
/>
dojo.query(".blurEvent").forEach(function(node, index, arr) {
dojo.connect(node, "onBlur", function() { /* do something */ });
});
In the function that is passed to dojo.connect you could add in some code to strip out the number on the end and use it to reference each filter_value_* input for validation.
dojo.connect()
Combobox documention
onBlur seems to work just fine for me, even in the HTML-declared widgets. Here's a very rudimentary example:
http://jsfiddle.net/kfranqueiro/BWT4U/
(Have firebug/webkit inspector/IE8 dev tools open to see console.log messages.)
However, for a more ideal solution to this, you might also be interested in some other widgets...
http://dojotoolkit.org/reference-guide/dijit/form/ValidationTextbox.html
http://dojotoolkit.org/reference-guide/dijit/form/Form.html
Hopefully this can get you started.