Adding numbers in AngularJS - angularjs

Just started learning AngularJS. I was trying to understand the two-way data binding by writing a code that adds two numbers from the input boxes.
Here's what I have written:
HTML
<div ng-app="cal">
<div ng-controller="calc">
<input type="text" ng-model="a"/>
<input type="text" ng-model="b"/>
<span>{{result}}</span>
</div>
</div>
JavaScript
var app=angular.module("cal", []);
app.controller("calc",function ($scope) {
$scope.result=Number($scope.a || 0)+ Number($scope.b || 0);
});
This, however, doesn't give the intended result i.e "result" is not updated automatically.
But the following code works:
HTML
<div ng-app="cal">
<div ng-controller="calc">
<input type="text" ng-model="a" ng-keyup="add()"/>
<input type="text" ng-model="b" ng-keyup="add()"/>
<span>{{result}}</span>
</div>
</div>
JavaScript
app.controller("calc",function ($scope) {
$scope.add=function(){
$scope.result=Number($scope.a || 0)+ Number($scope.b || 0);
}
});
Why do I need the "keyup" directive? Shouldn't the variable "result" be updated automatically as the values in the fields change?
I also created a jsfiddle here:
https://jsfiddle.net/Deadboy/m9ket0sL/

No, it shouldn't. The controller function is executed once, when angular sees the ng-controller in the DOM. It's not executed every time you type something in the input boxes. So the code computing the result is only executed once, before the user has had a chance to type anything in the inputs.
You don't need the keyup, though (and that wouldn't work if you pasted the value with your mouse, BTW). All you need is
$scope.add = function(){
return (Number($scope.a || 0)+ Number($scope.b || 0));
}
and in the view:
<span>{{ add() }}</span>
When doing it that way, angular will reevaluate the add() expression after each event that modifies the model, and update the DOM with the result of the expression.
If you want to compute the result only when a or b changes, you should be using ng-change, not ng-keyup.
Note that if your inputs are supposed to contain numbers only, you should use an input of type number, not text. In that case, $scope.a and $scope.b will be of type number, not string.

scope variable (a) and (b) are being updated since they are two-way binded.
variable a1 and b1 won't get the update since they only get updated when you initiate your controller "calc" and they are not two-way binded.
To update your result scope variable you can use ng-change to set variable a1 and b1 with updates from $scope.a and $scope.b
<div ng-app="cal">
<div ng-controller="calc">
<input type="text" ng-model="a" ng-change="updateResult()"/>
<input type="text" ng-model="b" ng-change="updateResult()"/>
<span>{{result}}</span>
</div>
/**
* Created by rajat on 12-Nov-16.
*/
var app=angular.module("cal", []);
app.controller("calc",function calc($scope) {
$scope.updateResult = function () {
var a1 = Number($scope.a || 0);
var b1 = Number($scope.b || 0);
$scope.result=a1+b1;
}
});

Related

Angularjs: How to get value of input without ng-model

I need to make some inputs by ng-repeat, and in my json file I have in object where is a property called name, like this:
"url":"find_company",
"values":[
{
"name":"company name",
"type":"input_search"
},{
"name":"company_phone",
"type":"input_search"
}
]
I want to make search in DB, in search you can find by any field or by two or more field. Field called the same as property of object. So by ng-keyup I need to send to my function
search(field, value)
two arguments. I want to do something like this
<div ng-repeat="value in param.values">
<input ng-if="value.type == 'input_search'"
ng-keyup="search(value.name, this.text)"
type="text">
How can a send to function text of this input without using ng-model? Where this.text is value of input.
since you are using ng-keyup, you can retrieve input value with $event.target.value.
comment: this is fit for normal event like onclick, but not fit for angular.
refer the below example.
angular.module("app", [])
.controller("myCtrl", function($scope) {
$scope.showValue = function(val) {
alert(val);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
<input type="test" ng-keyup="showValue($event.target.value)">
</div>
This is how you do it with ngModel:
<div ng-repeat="value in param.values">
<input ng-if="value.type == 'input_search'" ng-model="value.val" ng-keyup="search(value)" type="text">
And in your controller:
$scope.search = function( item ) {
console.log( item.val ); // Here you have the value using ngModel
console.log( item.name ); // Here you have the "name" property of the element inside the loop
}
As you can see, you CAN use ngModel and by passing the object itself to the function you can access its properties from the function in the controller.
Note that there's that this.text in the view - I don't know what it is exactly so I dropped it from the example to make things clearer, but you can use it in your code of course.
I know the question said without using ng-model. But I suspect you may want this because you want to customize when data-binding occurs. If that's the case, you can use ng-model-options with ng-change:
<input type="text" ng-model="yourModel" ng-model-options="{ updateOn: 'keyup' }" ng-change="search()" />
ng-change fires when the model has been updated, which is after keyup in this case. So the value of yourModel will be up to date when search() executes.

ng-change triggered before value is updated

I have a form which needs to save data each time something is changed. I've used ng-change on all form elements to trigger a form validation and a save. However in case of radio buttons, ng-change is triggered before the actual value is updated, thus resulting in an invalid form on the first try, and an outdated form all subsequent times.
I've set up a JSFiddle to illustrate this. The console prints out whether the form is valid or not. The same applies if I were to print the value of $scope.form.test.$modelValue.
// HTML
<div ng-controller="MyCtrl">
<form name="form">
<input type="radio" name="test" ng-model="test" value="yes" required ng-change="checkRadios()" /> Yes<br/>
<input type="radio" name="test" ng-model="test" value="no" required ng-change="checkRadios()"/> No
</form>
</div>
// JS
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.test = null;
$scope.checkRadios = function(){
console.log($scope.form.test.$modelValue);
}
}
Is my logic faulty, is this a valid bug, or does it work as expected? In the last case, what can I do to always get the actual value?
You need a delay to get the updated value of the $scope.form, so it is possible to achieve by using $timeout
http://jsfiddle.net/loen22/w7dpx57f/
$scope.checkRadios = function(){
$timeout(function () {
console.log($scope.form.$valid);
});
}

How to get the input value of an input on which a function is being called in angularjs? (Directive, ng-repeat)

how do I get a value of an input that is in ng-repeat? I want to be able to ng-repeat the value (as a default) but I also want to be able to change the value.
It's hard to explain what I mean but I can give you can example:
In my Directive (the relevant part):
ctrl.numbers = [1,2,3,4,5]
ctrl.myFun = function () {
console.log(ctrl.val)
};
My HTML:
<div ng-repeat="num in numbers">
<input type="text" value="{{num}}" ng-click="ctrl.myFun()">
</div>
So on click I want to get the "this" value of the input on which the function is being called. I thought this will be supereasy but every way I try to do it I get undefined. I tried to do it with scope { value : "#" } inside my directive and failed, I tried ng-model and ng-bind and failed as well.
I want to be able to attach the function to multiple fields so I don't want to hardcode any variables.
Many thanks!
Firstly, use ng-model because it's Angular and just pass the value to the function like so.
<div ng-repeat="num in numbers">
<input type="text" ng-model="num" ng-click="ctrl.myFun(num)">
</div>
ctrl.numbers = [1,2,3,4,5]
ctrl.myFun = function (val) {
console.log(val)
};
JSFiddle

Show/hide element AngularJS based on Controller boolean variable

I am trying to hide/show a portion of a form based on a Controller boolean variable. this is my html code:
<div id="sheetform-container" ng-controller="SheetController as SheetCtrl">
<form action="#">
<div class="sheetform-row" ng-show="canShow('Price')">
<div class="sheetform-left-col fl-left"><label for="sheetform-price">Price</label></div>
<div class="sheetform-midlle-col fl-left"><input type="text" class="sheetform-input" id="sheetform-price" name="price" value="$ 0.00" /></div>
<div class="sheetform-right-col fl-right"></div>
</div>
</form>
</div>
I have created a function that changes the Price attribute to true/false according to the value sent, its called setConfig. This is how the Controller code looks like:
ngApp.controller('SheetController', ['$scope', function($scope) {
$scope.Price = true;
$scope.canShow = function(field) {
return $scope.Price;
}
$scope.setConfig = function(config) {
$scope.Price = config.Price;
}
}]);
Any idea what am I missing?
Thanks!
If you are intending for price to be the actual price of something then you shouldn't be using that for the boolean in this case. Assign the price using ng-model. Also, don't use a capital letter to name a variable. Only classes should be capitalized.
<div id="sheetform-container" ng-controller="SheetController as SheetCtrl">
<form action="#">
<div class="sheetform-row" ng-show="showPrice">
<div class="sheetform-left-col fl-left"><label for="sheetform-price">Price</label></div>
<div class="sheetform-midlle-col fl-left"><input type="text" class="sheetform-input" id="sheetform-price" name="price" ng-model="price" /></div>
<div class="sheetform-right-col fl-right"></div>
</div>
</form>
</div>
Then in your controller you can remove the function you have and also initialize the variables
ngApp.controller('SheetController', ['$scope', function($scope) {
$scope.showPrice = true;
$scope.price = null;
}]);
I'm not sure how you are determining whether the price should be shown or not but you can either have $scope.showPrice assigned to a property in whatever object the form is for or if it's a toggle then you can just say:
<a href ng-click="showPrice = !showPrice"></a>
In the <div class="sheetform-row" ng-show="canShow('Price')">
canShow() function needs a boolean value so that ng-show can change the output accordingly.
'Price' is treated as a string 'Price' not a boolean in your controller.
So change it to ng-show="canShow(Price)",here Price's value will be true/false ,this will help ng-show to hide/show properly.
Also setConfig is not influencing the value of price right now.
Let me know if it helps you or u need further help.
you're missing $digest().
angular only updates DOM in digest loop.
official documentation
$watch how $apply runs $digest

Referencing the element that is calling a controller function Angularjs ( ng-change / ng-blur / ng-* ? )

The original question asked about how to determine which element called the controllers blurr function, but I didn't clarify that I was not specifically asking about ng-blur, but ng-* (ng-change, ng-focus, ng-mouseover, ng-*) in general. So, with that in mind:
How do I determine which element input is calling the blurr() and/or check() functions?
html
<body ng-app="test">
<div ng-controller="Cntrlr as cntrlr">
<form name="meta_test">
<input type="text" name='inpt' ng-model="cntrlr.inpt" ng-blur="cntrlr.blurr()" ng-change="cntrlr.check()" />
<input type="text" name='second' ng-model="cntrlr.second" ng-blur="cntrlr.blurr()" ng-change="cntrlr.check()" />
</form>
</div>
</body>
js
var app = angular.module("test", []);
app.controller("Cntrlr", ["$scope", function($scope){
this.blurr = function(){
alert("which input am I?");
alert("this is so meta.");
// ?
};
this.check = function(){
alert("this is how meta I am:");
alert(this);
}
$scope.Cntrlr = this; // see: (reference)
return $scope.Cntrlr;
}]);
You may be asking yourself "why would he want to do this?"
There are 2 reasons:
because I want to call:
$scope.user_form[meta_test.[(whatever this element is.name)]].$setValidity('spike', false);
because I'm curious. There has to be a simple way to do this.
(reference):
controller as syntax
Use this -
<input type="text" name='inpt' ng-model="cntrlr.inpt" ng-blur="cntrlr.blurr($event)" ng-change="cntrlr.check()" />
This returns the jQuery lite version of the event that causes the blurr function. Once you receive this element in your controller, you can pretty much do whatever you want with it.
The .target attribute of the event will give you the required element.
Should work
Try this:
<form name="meta_test">
<input type="text" name='inpt' ng-model="cntrlr.inpt" ng-blur="cntrlr.blurr()"
ng-change="cntrlr.check('One')" />
<input type="text" name='second' ng-model="cntrlr.second"
ng-blur="cntrlr.blurr()" ng-change="cntrlr.check('Two')" />
</form>
In JS,
this.check = function(Type){
if(Type == "One"){
//Then it is the first text box.
}else if(Type == "Two"){
//Then it is the second text box.
}
}

Resources