How to use hasOwnProperty with AngularJS Directive `attrs` object - javascript

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.

Related

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

Why 1. returns an empty string when I try to get value of an input type number using javascript and html5?

I have a normal input as follows:
<input type="number" name="quantity" id="myInput">
If I type "1." (without the quotes of course) when I try to get the value of the input with
document.getElementById("myInput").value
Only an empty string is obtained.
Is there any other way to get the "1." input with javascript?
Edit
I am working using Polymer 1.0 and databinding, so in my example I showed using normal JavaScript syntax with the intention of finding a solution to my problem using only javascript.
I just want to know how to access a property that returns the value of the input, and which I believe should be stored in some property of the object.
If you use <input type="number"> the element is enriched with an extra attribute, valueAsNumber. So instead of
document.getElementById("myInput").value
use
document.getElementById("myInput").valueAsNumber
valueAsNumber will return NaN instead of blank if the value entered in the input not is convertable to a number. There is also a validity attribute holding information of the status of the current value, both according to the value as supposed number but also according to the number input's settings, i.e "why is the number invalid".
Fun with number inputs, try this out in various browsers :
<input type="number" name="quantity" id="myInput" ><br>
<input type="text" id="value" ><br>
<input type="text" id="valueAsNumber" ><br>
<input type="text" id="validity" ><br>
document.getElementById("myInput").onkeyup = function() {
document.getElementById("value").value = this.value;
document.getElementById("valueAsNumber").value = this.valueAsNumber;
document.getElementById("validity").value = '';
for (validity in this.validity) {
if (this.validity[validity]) {
document.getElementById("validity").value+=validity+' ';
}
}
}
actually quite informative, if you want to investigate exactly why you get an empty value back from the input -> http://jsfiddle.net/oaewv2Lr/ Have tried with Chrome, Opera and FF - Chrome seems to be the most "forgiving" browser of those three.
I found a way to get invalid values:
Focus the input.
Select its contents using execCommand().
Grab the selection using window.getSelection().
Example:
document.querySelector('input[type="submit"]').addEventListener('click', function() {
var inp= document.getElementById('myInput');
inp.focus();
document.execCommand('SelectAll');
var value = window.getSelection().toString();
document.getElementById('output').textContent = value;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" name="quantity" id="myInput">
<input type="submit">
<div id="output"></div>
It won't work if you will enter 1., as 1. is not a valid number.
Update: It seems that your use of type="number" means that certain values won't come back. You can switch it to a type="text" and do the checking yourself:
document.getElementById('mySubmit').addEventListener('click', function() {
var value = document.getElementById('myInput').value;
if ( value != parseFloat(value) )
alert('Invalid Number');
document.getElementById('myOutput').innerHTML = value;
});
<input type="text" name="quantity" id="myInput">
<input type="submit" id="mySubmit">
<div id="myOutput"></div>

Knockout validation throttle

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);
`

knockout js if statement to Display value based on boolean data type

I am trying to Display a value based on a table value of True or False. For example if the Value is True then I want it to Say Supported and If it's False then I want it to Say Not Supported! This is my html code
<p><input type="text" data-bind="value: Support" /></p>
Java script Code
$(function() {
dm.viewModel = function() {
var clients = ko.observableArray(),
selectedClient = ko.observable(),
clientChanged = function() {
$.getJSON(dm.WebServices + "/dm/get/clientinfo?client=" + encodeURIComponent(selectedClient()), function(data) {
if (data != null) {
dm.viewModel.Name(selectedClient());
dm.viewModel.Support(data[0]['Support']);
}
})
$('#divClientData').show();
},
LoadClients = function() {
$('#divClientData').hide();
$.getJSON(dm.WebServices + "/dm/get/clientlist", function(data) {
$.each(data, function(key, val) {
clients.push(val);
});
});
},
Name = ko.observable(),
Support = ko.observable(),
return {
Name: Name,
Support: Support
};
}();
ko.applyBindings(dm.viewModel);
dm.viewModel.LoadClients();
})
In this kind of case you can evaluate the property and render based on the value. Even a function can be provided inside the binding. You can use this:
<input type="text" data-bind="value: Support() ? 'Supported' : 'Not Supported'" />
You can do that with the if binding
See documentation here
Example from the docs:
<label><input type="checkbox" data-bind="checked: displayMessage" /> Display message</label>
<div data-bind="if: displayMessage">Here is a message. Astonishing.</div>
So for you
<div data-bind="if: Support">Supported</div>
<div data-bind="ifnot: Support">Not Supported</div>
Edit: The other answers suggesting using the value binding with a ternary condition are probably a better way to accomplish this. I'll keep this up as a reference, but I recommend that solution.
What you're looking for, in this case, is ko.computed().
EDITED: (Support appears to be in-use as a value from the data set)
Add a new value to your ViewModel, something like this:
IsSupported = ko.computed(function(){
if(this.Support() == true){
return "Supported";
} else {
return "Not Supported";
}
}, this)
Then, in your markup, you will have to change your data-bind just slightly:
<p><input type="text" data-bind="value: IsSupported" /></p>
Alternatively, if you don't want to change your Support field, you'll have to do something like this in your HTML, as suggested by other commenters:
<p><input type="text" data-bind="value: (Support() ? 'Supported' : 'Not Supported')" /></p>
I'd recommend the former, however, as really, you should keep that logic tucked away inside your ViewModel.
(See the KO docs for more info on computed: http://knockoutjs.com/documentation/computedObservables.html)
In my work I use KO boolean conditions like this:
<div id="bla" data-bind="visible: position != value"></div>
KO is very useful for those types of problems.

Knockout computed gives Function expected error in IE only

I'm getting a "SCRIPT5002: Function expected" that only happens in IE. I'm currently testing against version 9. It happens when I use a previously defined computed observable inside of another computed observable.
My application is a bit more complex than this, so I've reproduced the error with the much simpler code below. The error happens on the line z = self.subtotal(); when you enter a number in for Number 1, Number 2, and Number 3 (and tab out).
This error does not occur in Chrome or Firefox and I've googled for quite a while. Hopefully someone can help un-stick me.
Here is the link to the jsfiddle: http://jsfiddle.net/kCmTg/
Here is the javascript:
function putVars() {
self = this;
self.number1 = ko.observable();
self.number2 = ko.observable();
self.subtotal = ko.computed(function () {
return parseFloat(self.number1()) + parseFloat(self.number2());
}, self, { deferEvaluation: true });
self.number3 = ko.observable();
self.number4 = ko.observable();
self.total = ko.computed(function () {
var x, y, z;
x = self.number3();
y = self.number4();
z = self.subtotal();
return parseFloat(x) + parseFloat(y) + parseFloat(z);
}, self, { deferEvaluation: true });
}
$(function () {
ko.applyBindings(new putVars());
});
Here is the html:
<h4>Calc 1</h4>
<label for="Number1">Number 1: </label><input id="Number1" type="text" data-bind="value: number1" />
<label for="Number2">Number 2: </label><input id="Number2" type="text" data-bind="value: number2" />
<label for="Subtotal"><b>Subtotal: </b></label><input id="Subtotal" type="text" data-bind="value: subtotal" readonly="readonly" />
<hr />
<h4>Calc 2</h4>
<label for="Number3">Number 3: </label><input id="Number3" type="text" data-bind="value: number3" />
<label for="Number4">Number 4: </label><input id="Number4" type="text" data-bind="value: number4" />
<label for="Total"><b>Total:</b> </label><input id="Total" type="text" readonly="readonly" data-bind="value: total" />
This has a similar cause to this one: knockout.js Computed observable called twice in Internet Explorer and is caused by the fact that in IE<10, Knockout has some special code to deal with getting an autocomplete value from the field. It does this even if the field is read-only as in your case. It does check, however, for the autocomplete attribute. So you could fix it like this:
<input id="Subtotal" type="text" data-bind="value: subtotal" autocomplete="off" readonly="readonly" />
There is also a bug in Knockout at play here--that it will overwrite a computed observable passed to a two-way binding. This is already fixed in the development version of Knockout to be released as version 2.3.0 (probably in April 2013). To work around this, you can pass the value of the observable to the binding instead of the computed observable itself, like this:
<input id="Subtotal" type="text" data-bind="value: subtotal()" readonly="readonly" />
It appears you've discovered a bug in IE or KnockoutJS, likely exposed by Knockout's bindings, where Knockout is pushing a value into an observable, but in IE9, it overwrites the property.
This doesn't occur on IE10, suggesting it's a bug in IE9. I'd guess Knockout has something where it's checking if some value is a writable observable function and it's being reported incorrectly on IE9.
Interestingly, if you change KO computed to use a read/write, the error ceases:
self.subtotal = ko.computed({
read: function() {
return parseFloat(this.number1()) + parseFloat(this.number2());
},
write: function(val) { }
}, self);
Perhaps that is a sufficient work-around?
Please check to see if you observable has a value being passed as a parameter or not. for example budgetlineviewmodel.total = total(5). I have tried using budgetlineviewmodel.total = 5. but with no success.
Knockout Observables are nothing but functions internally and have you have to pass a value inside brackets which internally return the same value.
Chrome is lenient in allowing budgetlineviewmodel.total() to tolerate null value when no parameter is passed.
hope this helps.
Cheers !
budgetlineviewmodel.Save = function () {
var currentTotalAmt = $('#txtTotal').val();
budgetLineViewModel.Total(currentTotalAmt);
}

Categories

Resources