Knockout validation throttle - javascript

Hi i have a css binding on a input type which adds the class CircleErrors if it matches my function. My problem is it has a delay on taking the class off it only happens when i tab off the input box. I want the class to be removed on key down of the keyboard.. i know there is a throttle you can use for knockout but i am not sure how to go about doing it.
<input id="firstName" type="text" placeholder="First name" data-bind="value: Registration.FirstName, css: { CircleErrors: Registration.FirstName().length == 0 && Registration.FirstNameValidation(), valueUpdate: 'afterkeydown' }">

You've misplaced your valueUpdate parameter. It's inside the css parameter - you need to move it outside the }:
<input id="firstName" type="text" placeholder="First name" data-bind="value: Registration.FirstName, css: { CircleErrors: Registration.FirstName().length == 0 && Registration.FirstNameValidation() }, valueUpdate: 'afterkeydown'">
Here's a demo with it working

Use the textInput binding instead of the value binding for the first name property (and for any text input fields for that matter). To quote the docs
Unlike the value binding, textInput provides instant updates from the
DOM for all types of user input, including autocomplete,
drag-and-drop, and clipboard events.
You don't need the valueUpdate binding any more, however it was inside your CSS binding so would not have had any effect.
<input id="firstName" type="text" placeholder="First name" data-bind="textInput: Registration.FirstName, css: { CircleErrors: Registration.FirstName().length == 0 && Registration.FirstNameValidation() }">

Demo
this is what you looking for
` var reg = new (function() {
var self = this;
this.FirstName = ko.observable('');
this.checkifEmpty = ko.observable(false);
this.check=function(){
if(this.FirstName()!=null&&this.FirstName()!=undefined && this.FirstName() !=''){
this.checkifEmpty(true);
}else{
this.checkifEmpty(false);
}
}
this.FirstNameValidation = function() {
return true;
}
})();
ko.applyBindings(reg);
`

Related

HTML text input not updating with Knockout Bindings

I am trying to automatically add slashes for a DOB input field but Knockout bindings are not playing nice.
<input
name=x
size=10
maxlength=10
class="span12"
placeholder="Date of birth (MM/DD/YYYY)"
onkeyup="this.value=this.value.replace(/^(\d\d)(\d)$/g,'$1/$2').replace(/^(\d\d\/\d\d)(\d+)$/g,'$1/$2').replace(/[^\d\/]/g,'')"
data-bind="value:visitor().dateOfBirth, valueUpdate:'keyup'" />
The issue now is that the Knockout Js bindings are not allowing the slashes value to be automatically updated. When I enter dates in the text box no slashes show up. How do I set up a subscriber for myViewModel to modify the value whenever it changes?
You should do something along these lines - note you should remove the inlined onkeyup from your input tag and let your view model handle it:
var vm = function () {
var self = this;
self.dateOfBirth = ko.observable();
self.insertSlashes = function () {
var currentValue = self.dateOfBirth();
self.dateOfBirth(currentValue
.replace(/^(\d\d)(\d)$/g,'$1/$2')
.replace(/^(\d\d\/\d\d)(\d+)$/g,'$1/$2')
.replace(/[^\d\/]/g,'')
);
}
}
ko.applyBindings(new vm());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<input
placeholder="Date of birth (MM/DD/YYYY)"
data-bind="value: dateOfBirth, valueUpdate:'keyup', event: { keyup: insertSlashes } "
/>

How to use hasOwnProperty with AngularJS Directive `attrs` object

I have a directive named ip-abc which is used to check the input values of fields and convert to dollar formatted values. I have a condition where if we have the value as "0", then I will convert that to $0.
ipabc.js
var filterFunc = function (value) {
if(value == '0'){
if(attrs.hasOwnProperty('ipZeroDollar')){
var currencyValue = $filter('currency')(value);
currencyValue = currencyValue.toString();
return currencyValue.replace('.00','');
}
}
The problem which I am facing is that, how can I set ipZeroDollar = true in HTML. As of now, (attrs.hasOwnProperty('ipZeroDollar')) is coming as false.
<div ng-class = {'//something'}
<input type="tel" name="amount" class="form-control" ng
model="Data.Amount" maxlength="15" required ip-abc/>
</div>
The problem which I am facing is that, how can I set ipZeroDollar = true in HTML. As of now, (attrs.hasOwnProperty('ipZeroDollar')) is coming as false.
The camelCase needs to be normalized to kebab-case in the HTML:
<input type="tel" name="amount" class="form-control"
ng-model="Data.Amount" maxlength="15" required
ip-abc ip-zero-dollar />
For more information, see
AngularJS Developer Guide - Attribute Normalization
AngularJS attrs Type API Reference
The DEMO
angular.module("app",[])
.directive("ipAbc", function() {
return {link: postLink};
function postLink(scope,elem,attrs) {
var hasIpZeroDollar = attrs.hasOwnProperty("ipZeroDollar");
console.log("hasIpZeroDollar",hasIpZeroDollar);
}
})
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app"
<input type="tel" name="amount" class="form-control"
ng-model="Data.Amount" maxlength="15" required
ip-abc ip-zero-dollar />
</body>
This is how you use hasOwnProperty().
let obj = {color: 'yellow'}
obj.hasOwnProperty('color') // returns true
It seems like you would want to call hasOwnProperty() on Data since that looks like its an object, and that is where you are getting the amount.

Assign v-validate multiple validation rules (predefined and custom)

I can't figure out how to assign multiple rules to vee-validate. Usualy you pipe | the rules inside v-validate attribute, but the problem is that I also try to include one custom method.
<input id="number" type="tel" v-model="cardDetail.number" v-card-focus
class="form__input"
v-validate="'required'" <!-- need to add requireNumberIfCreditCard method -->
data-vv-validate-on="blur"
name="number" required>
<label for="number" class="form__label">
{{ $root.trans.translate('cardNumber') }}
</label>
<p class="form__error" v-show="errors.has('number')">
{{ errors.first('number') }}
</p>
This is my javascript
export default {
data() {
return {
cardDetail: {
number: '',
}
}
},
computed: {
requireNumberIfCreditCard() {
if (this.paymentMethod === 'creditCard') {
return this.cardDetail.number ? "required" : "";
}
}
}
};
How should my HTML look like so I will be also able to add custom mthods to vee-validate? If you need any additional informations, please let me know and I will provide. Thank you!
The attribute v-validate is bound to your data, so you can use anything you want within it. Further, it supports different syntaxes - one, which you're using is a string (i.e. 'required'). Another form it supports is an object, which is what you need:
<input id="number" type="tel" v-model="cardDetail.number" name="number"
v-validate="{ required: (requireNumberIfCreditCard == 'required') }">
I recommend you change your computed value to return true/false, in which case you can just use it directly.
Working example: https://codesandbox.io/s/km4lw12823

How to reference "this" in a function

I want to validate several input fields. The code below works fine, except for the focus method. I expect that it can not interpret the "input" variable which relates to the input location on the form. Question: How do I reference the location of the specific input, bearing in mind that there are 20+ inputs ? tks !
function validateInput(quantity,input)
{
if (quantity.value !== " ") {
if(isNaN(quantity)) {
$(".myerror_alert").append('<div class="alert alert-danger"><strong>Warning!</strong> You have entered an non valid character, go back and enter a real number </div>');
input.focus(); // THIS DOES NOT WORK
return false;
}
}
return true;
}
$(".product_table").on('change', '.edit_quantity',function (){
var quantity = $(this).parents(':eq(1)').find('input').filter(".edit_quantity").val();
var input = $(this).parents(':eq(1)').find('quantity').filter(".edit_quantity");
validateInput(quantity, input);
// MORE CODE GOES HERE //
});
HTML:
<tr class='delete_row'>
<td><input class="product_id form-control" readonly="readonly" name="product_id[0]" type="text" value="123"></td>
<td><input class="edit_product_id form-control" readonly="readonly" name="product_id[0]" type="text" value="Euroshake Blackstone"></td>
<td><input class="edit_quantity" name="product_id[0]" type="text" value="120"></td>
<td id="price"><input class="unit_price form-control" readonly="readonly" style="text-align:right;" name="price" type="text" value="120.00"></td>
<td><input class="line_cost form-control" readonly="readonly" style="text-align:right;" name="cost" type="text" value="14400.00"></td>
<td>
<span style="padding-left:12px;"><input name="delete" type="checkbox" value="123"></span>
</td>
</tr>
What I did was supose that in this part .find('quantity') you was probably meaning .find('input') as its previous statement, then I figure out that you were working with the same element there. So being the same element, you don't need to hold it's reference(in input var) and it's value(quantity var) to pass into validateInput. As this is a function, why not work with less code and make the function handles it, right? So I've changed it to pass only the element reference and inside the function with this condition if ($input.val().length > 0 && isNaN($input.val())) I could check if element ins't empty and also if it isn't a number:
function validateInput(input)
{
var $input = $(input);
if ($input.val().length > 0 && isNaN($input.val())) {
$(".myerror_alert").append('<div class="alert alert-danger"><strong>Warning!</strong> You have entered an non valid character, go back and enter a real number </div>');
input.focus();
return false;
}
return true;
}
$(".product_table").on('change', '.edit_quantity',function (){
validateInput(this);
});
Demo
One important mistake you've done that you've workaround it - probably - without noticing it, is that you navigate through the element tree to find the input, but when you do $(".product_table").on('change', '.edit_quantity' you're in fact binding an event in all elements with class edit_quantity inside the element with class product_table, so inside the event, your this already is the input, you don't need to go after it, as I did:
validateInput(this);
I hope this helps.

Text as place holder for textbox input?

I notice that at some websites like http://academia.edu/, the signup form has some "place-holder" in their text input field. Such that in a textbox, there's no label but a rather slight font "First name" word inside the text box.
When using Firebug to investigate, I see the following code:
<input class="standard_text magic-default magic-default-on" id="user_first_name" name="user[first_name]" size="30" type="text" value="First Name">
It looks like there's some "magic" javascript happen behind the scene. But since I'm not familiar with javascript debugging yet, I can't trace out how they do that yet.
Does anyone know how to produce that effect?
For modern browsers you can use the HTML5 placeholder attribute.
This will achieve the result you're after without any Javascript and will scale (won't do anything) in older browsers.
<input placeholder="First Name">
To get this working in older browsers you can include a little bit of jQuery:
$('input:text').focus(function(){
if ( $( this ).val () === $( this ).attr ( 'placeholder' ) ) {
$(this).val('');
}
}).blur(function(){
if($(this).val() == "")
{
$(this).val($(this).attr('placeholder'))
}
}
);
Working Example
You have to create a "onFocus" event handler for the input box, and clear the value of said input box. Off course you only clear the value if it's the default value ("First Name" in your example), so that you don't clear away whatever user entered if he returns to the input later.
You could also attach a "onBlur" event handler, and restore the value of the input box back to the default value (if user didn't enter anything).
<input id="user_first_name" name="user[first_name]" size="30" type="text" value="First Name" onFocus="inputFocus('First Name', this)" onBlur="inputBlur('First Name', this)">
<script type="text/javascriptt">
function inputFocus(ph, el){
if(el.value == ph)
el.value = "";
}
function inputBlur(ph, el){
if(el.value == "")
el.value = ph;
}
</script>
HTML5 placeholder is what you're looking for:
http://diveintohtml5.info/forms.html
In your case it would be:
<input name="firstname" placeholder="First name">
But also you can do it 100% with javascript:
http://lab.dotjay.co.uk/experiments/forms/input-placeholder-text/

Categories

Resources