Angular UI-Validate without input field (validate expression) - javascript

Im using ui-validate utils
https://github.com/angular-ui/ui-validate
The problem is to validate expression on the form without input field.
For example? I have an object
$scope.item = { field1 : 0, field2: 0, field3: 0 };
I would like to receive the error, provided expression: field1 + field2 + field3 == 0
It is common validation for the whole form. Not for some input.

You can write a small function like this (not really sure, you need to use ui-validate for this):
$scope.validate = function () {
var sum = 0;
// Sum every non Angular key
angular.forEach($scope.items, function (value, key) {
// You can also add another check below "angular.isNumber(value)" if you have some text fields
if (key.charAt(0) !== '$') {
// Call "parseInt()" method here if values are in string
sum += value;
}
});
return sum !== 0;
}
Now, display it at somewhere in your form:
<form>
<div ng-show="!validate()">There is some error. Sum can't be zero</div>
<!-- Your fields below -->
</form>

ui-validate can only be used within input tags as there is a requirement for ng-model. ng-show binding to a function would work.
Here is an example:
http://codepen.io/ctwoodwa/pen/eJmyYg
angular.module('ngExample', ['ngMessages'])
.controller('elemController', Controller1);
function Controller1() {
vm = this;
vm.item = { field1 : 0, field2: 0, field3: 0 };
vm.validate = validate
function validate() {
// Determine if the form is valid.
return (vm.item.field1 + vm.item.field2 + vm.item.field3 == 0);
};
}
<div ng-app='ngExample' ng-controller="elemController as vm">
<form name="exampleForm">
<label for="field1">Field1</label>
<input type="number" name="field1" ng-model="vm.item.field1"/>
<label for="field2">Field 2</label>
<input type="number" name="field2" ng-model="vm.item.field2"/>
<label for="field3">Field 3</label>
<input type="number" name="field3" ng-model="vm.item.field3"/>
<div ng-show="vm.validate()">
<div class="error">This form is not valid</div>
</div>
<button>Submit</button>
</form>
</div>

Related

How to pass dynamic value to jquery validation function

I have a form which have some dynamically added input,
Here i input have total_amt = 100;
How can i, form should not submit until, sum of all the dynamically added inputs must be equal to total_amt
Here is my code.
$(function(){
var i = 1;
$('#add_more').click(function(event) {
event.preventDefault();
$('input.items').last().attr('name', 'item['+i+']');
$('#cart_items').append($('#tmp_cart').html());
$('input[name="item['+i+']"]').rules("add", {
required: true,
depositsSum : function(){
return $(this).val();
},
messages:'Sum of total items should be equal to 100',
});
i++;
});
$.validator.addMethod("depositsSum", function(value, element, params)
{
var amnts = 0;
$(params[0]).each(function() {
amnts += parseFloat($(this).val());
});
return amnts;
});
$("#myForm").validate({
rules: {
'item[0]': {
required:true
}
}
});
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/additional-methods.min.js"></script>
<form action="" method="POST" id="myForm">
Total Items<input type="text" value="100" name="total_amt" id="total_amt">
<div id="cart_items">
Items<input type="text" name="item[0]" class="items"><br/>
</div>
<button id="add_more">Add More</button>
<input type="submit" name="submit" value="submit">
</form>
<div id="tmp_cart" style="display: none;">
<label>
Items<input type="text" name="item[]" class="items">
</label><br/>
</div>
Two flaws in your code...
Within your .rules() method:
depositsSum : function(){
return $(this).val();
},
You're trying to set the parameter of you custom rule to the value of the field. This is complete nonsense. A parameter is something like Max: 10, where 10 is the parameter and it defines the rule; it's never the actual value of the field, which, by the way, always changes and is empty when the page loads. When you want to invoke the custom rule, set the parameter to true.
And related to the next problem...
Within your .addMethod() method:
$(params[0]).each(function() {
amnts += parseFloat($(this).val());
});
The params argument would be useless in your case, since the parameter can not be used for passing the dynamic values of other fields. Use a jQuery selector to grab the other fields. Since the name begins with item, use the "starts with" selector.
$('[name^="item"]').each(function() {
amnts += parseFloat($(this).val());
});

How to detect changes in form and set new state?

I have HTML form with set of elements(inputs).
So, how to detect changes in any input and set new statement in object var data?
For example:
<input type="text" name="parameter" value="30">
When I make chnages in input I need to get output object data as:
var = data = ["paraeter" : 30];
for watch the value on change in angular you should use ng-change and ng-model
var app = angular.module("app", []).
controller("ctrl", function($scope) {
$scope.info = {
parameter: 30,
parameters: {
children: 40
}
};
$scope.callBackIfChange = function(){
console.log($scope.info);
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<form>
<label>empty value</label>
<input type="text" ng-model="info.name" ng-change="callBackIfChange()">
<br>
<br>
<label>has default value</label>
<input type="number" ng-model="info.parameter" ng-change="callBackIfChange()">
<br>
<br>
<label>nested</label>
<input type="number" ng-model="info.parameters.children" ng-change="callBackIfChange()">
</form>
<hr>
<b>output:</b> {{info | json}}
</div>
Here is the Jquery code covering your cases (onload and input change) without hard-coding the name attributes of inputs tags:
var inputValuesObj = {}; // << Your Object
$(document).ready(function() {
getDefaultInputValues();
});
$(document).on("load keyup", "input", function() {
getDefaultInputValues();
});
function getDefaultInputValues() {
$("input").each(function(index) {
inputValuesObj[$(this).attr("name")] = $(this).val();
});
$("div#res").html(JSON.stringify(inputValuesObj));
}
Your test here - https://jsfiddle.net/uo08fedh/20/
Hope it helps!

Dynamic form Angular issue

I have written this code online dynamic form jsFiddle code
The total and grand total are not auto updating. I had a more simple example before and it was working with a single model item, but then I made an array and now it won't work. My real program I am building is going to have many more fields and I am trying to create a pre-example to show it will work. Can someone quickly see what dumb thing I am forgetting?
<div ng-controller="MyCtrl">
<form name="myForm">
<div ng-repeat="item in items track by $index">
<input type="text" ng-model="item.a">
<input type="text" ng-model="item.b">
<input type="text" ng-model="item.c">
<label>Total: </label><label ng-bind="total(item)"></label>
</div>
</form>
<div>
<label>Grand Total: </label><label ng-bind="grandTotal()"></label>
</div>
</div>
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function($scope) {
$scope.items = [
{
a: 0, b: 0, c: 0
},
{
a: 0, b: 0, c: 0
}];
$scope.total = function(item) {
var result = item.a * item.b * item.c;
return isNaN(result) ? 0 : result;
};
$scope.grandTotal = function() {
var result = 0;
angular.forEach($scope.items, function(item) {
result += $scope.total(item);
});
return isNaN(result) ? "" : result.toString();
};
});
ng-bind should be without $scope. You don't need to mention $scope in view bindings, it directly refers to $scope/this(context) of controller.
Other than that additionally change all input's ng-bind to ng-model to enable two way binding over all input fields.
Markup
<input type="text" ng-model="item.a">
<input type="text" ng-model="item.b">
<input type="text" ng-model="item.c">
ng-bind="total(item)"
Forked JSFiddle
Use
<input type="text" ng-model="item.a">
instead of
<input type="text" ng-bind="item.a">
Updated fiddle http://jsfiddle.net/Lhkedykz/17/

model got 'undefined' when $setValidity set to false

I have a form with one input field, and I validate that input when the value changes by using $setValidity .But the problem is when $setValidity set to false (invalid) the model is no longer updating, it holds value 'undefined' .
Here is my HTML :
<form name="frmEnrollPaymentPlan" novalidate autocomplete="off">
<div class="form-group" ng-class="{'has-error':(frmEnrollPaymentPlan.dwnAmt.$invalid && !frmEnrollPaymentPlan.dwnAmt.$pristine)||frmEnrollPaymentPlan.dwnAmt.$error.validateDownPaymentAmount}">
<label>Downpayment</label>
<input type="text" class="form-control" name="dwnAmt" ng-model="EnrollPaymentPlanViewModel.DownPaymentAmount" required ng-change="downPaymentChanged()" ng-model-options="{allowInvalid: true}">
<span ng-show="frmEnrollPaymentPlan.dwnAmt.$error.validateDownPaymentAmount" ng-class="{'error':frmEnrollPaymentPlan.dwnAmt.$error.validateDownPaymentAmount}">Cannot be less than down payment amount</span>
</div>
</form>
and Here is my javascript code:
$scope.downPaymentChanged = function () {
if (!isNaN($scope.EnrollPaymentPlanViewModel.DownPaymentAmount)) {
var downPaymentAmount = parseFloat($scope.EnrollPaymentPlanViewModel.DownPaymentAmount);
var minDownPaymentAmount = parseFloat($scope.EnrollPaymentPlanViewModel.MinDownPaymentAmount);
if (downPaymentAmount < minDownPaymentAmount) {
$scope.frmEnrollPaymentPlan.dwnAmt.$setValidity("validateDownPaymentAmount", false);
}
else {
$scope.frmEnrollPaymentPlan.dwnAmt.$setValidity("validateDownPaymentAmount", true);
}
}
}

How do I prevent invalid characters from being entered into a form?

For example, if I have a form and I don't want the user to enter numbers in it and I validate it with a function containing a regular expression, how do I prevent the invalid character the user entered (in this example, a digit) from showing up in the text form if it fails the regular expression test?
This is the function I tried and the select list I tried it on (in other words, this isn't the whole program). I tried returning false to the onkeypress event handler but what the user enters into the textbox still goes through.
function noNumbers(answer) { //returns false and displays an alert if the answer contains numbers
if (/[\d]+/.test(answer)) { // if there are numbers
window.alert("You can not enter numbers in this field");
return false;
}
}
<form action="get" enctype="application/x-www-form-urlencoded">
<select id="questions" name="questions">
<option value="no_numbers">What is the name of the city where you were born?</option>
<option value="no_letters">What is your phone number?</option>
<option value="no_numbers">What is the name of your favorite pet?</option>
<option value="no_letters">What is your social security number?</option>
<option value="no_numbers">What is your mother's maiden name?</option>
</select>
<p><input type="text" name="answer" onkeypress="validateAnswer();" /></p>
</form>
This validation works great for stripping invalid characters on the fly as you enter them in the relevant field. Example:
<form id="form1" name="form1" method="post">
Email:
<input type="text" name="email" id="email" onkeyup='res(this, emailaddr);' ; </form>
<script>
var phone = "()-+ 0123456789";
var numb = "0123456789";
var alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ #-'.,";
var alphanumb = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ #-.'1234567890!?,:;£$%&*()";
var alphaname = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ,-.1234567890";
var emailaddr = "0123456789#._abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
function res(t, v) {
var w = "";
for (i = 0; i < t.value.length; i++) {
x = t.value.charAt(i);
if (v.indexOf(x, 0) != -1)
w += x;
}
t.value = w;
}
</script>
Then you would simply change the second value of the javascript call to the type of data you want entered in the field using the variables that are defined within the code.
This is the function you are looking for
function validateAnswer(src) {
var questions = document.getElementById("questions");
var rule = questions.options[questions.selectedIndex].value;
if(rule=="no_numbers") src.value = src.value.replace(/\d/g, '');
if(rule=="no_letters") src.value = src.value.replace(/\w/g, '');
}
just send the input field reference to the function and set it to onkeyup event instead:
<input type="text" name="answer" onkeyup="validateAnswer(this);" />
you should also hook the onchange event of the selectbox to reset the value of the input box. I suggest you also consider the HTML5 pattern attribute. See
the fiddle
patern attribute support
workaround for unsupported browsers
You get the key being pressed from the event object passed to the handler.
input type="text" name="answer" onkeypress="validateAnswer(this, event);" />
function validateAnswer(element, event) {
if (event.charCode) {
if (/\d/.test(String.fromCharCode(event.charCode))) {
window.alert("You can not enter numbers in this field");
return false;
}
}
}
Googling for "onkeypress event" finds many examples of this.
Make your life simpler by adding an extra parameter to your validateAnswer function like this:
<input type="text" id="answer" name="answer" onkeyup="validateAnswer(this);" />
Then you can define your validateAnswer like this:
function validateAnswer(elem){
elem.value = elem.value.replace(/[^\d]/g, '');
}
Here an example: http://jsbin.com/iwiduq/1/

Categories

Resources