I am trying to do some calculation but it is getting done as soon as I enter the amount. I just want this to happen on click of a button rather than automatically.
What I have done so far:
<!DOCTYPE html>
<html ng-app="myAppModule">
<head>
<title>Angular JS - programming-free.com</title>
<link href="https://dl.dropbox.com/u/96099766/DetailModalExample/bootstrap.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="lib/angularjs.min.js"></script>
</head>
<body>
<div ng-controller="myAppController" style="text-align:center">
<p style="font-size:28px;">
Enter Quantity:
<input type="text" ng-model="quantity"/>
</p>
<h2>Total Cost: Rs.{{calculateval(quantity,10)}}</h2>
</div>
<script type="text/javascript">
var myAppModule = angular.module('myAppModule', []);
myAppModule.controller('myAppController', function($scope,calculateService) {
$scope.quantity=1;
$scope.calculateval = function(xval,yval) {
return calculateService.calculate(xval,yval);
}
});
// Service
myAppModule.factory('calculateService', function(){
return {
calculate: function(xval,yval){
return xval*yval;
}
}
});
</script>
</body>
</html>
The calculation occurs immediately since the calculation call is bound in the template, which displays its result when quantity changes.
Instead you could try the following approach. Change your markup to the following:
<div ng-controller="myAppController" style="text-align:center">
<p style="font-size:28px;">Enter Quantity:
<input type="text" ng-model="quantity"/>
</p>
<button ng-click="calculateQuantity()">Calculate</button>
<h2>Total Cost: Rs.{{quantityResult}}</h2>
</div>
Next, update your controller:
myAppModule.controller('myAppController', function($scope,calculateService) {
$scope.quantity=1;
$scope.quantityResult = 0;
$scope.calculateQuantity = function() {
$scope.quantityResult = calculateService.calculate($scope.quantity, 10);
};
});
Here's a JSBin example that demonstrates the above approach.
The problem with this approach is the calculated result remains visible with the old value till the button is clicked. To address this, you could hide the result whenever the quantity changes.
This would involve updating the template to add an ng-change on the input, and an ng-if on the result:
<input type="text" ng-change="hideQuantityResult()" ng-model="quantity"/>
and
<h2 ng-if="showQuantityResult">Total Cost: Rs.{{quantityResult}}</h2>
In the controller add:
$scope.showQuantityResult = false;
$scope.calculateQuantity = function() {
$scope.quantityResult = calculateService.calculate($scope.quantity, 10);
$scope.showQuantityResult = true;
};
$scope.hideQuantityResult = function() {
$scope.showQuantityResult = false;
};
These updates can be seen in this JSBin demo.
Related
I wish to share a service value between one or more controllers (only one in the following example but that's not the point).
The problema is that the value hold in the service is not bound and shown in the view.
The code (derived from angularjs basic service example) is:
(function(angular) {
'use strict';
angular.
module('myServiceModule', []).
controller('MyController', ['$scope', 'notify','$log', function($scope, notify, $log) {
$scope.callNotify = function(msg) {
notify.push(msg);
};
$scope.clickCount = notify.clickCount();
$log.debug("Click count is now", $scope.clickCount);
}]).
factory('notify', ['$window','$log', function(win,$log) {
var msgs = [];
var clickCounter = 0;
return {
clickCount: function() {
clickCounter = msgs.length;
$log.debug("You are clicking, click count is now", clickCounter);
return clickCounter;
},
push: function(msg) {
msgs.push(msg);
clickCounter = msgs.length;
$log.debug("Counter is", clickCounter);
if (msgs.length === 3) {
win.alert(msgs.join('\n'));
msgs = [];
}
}
}
}]);
I wish the counter to be displayed on page:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-services-usage-production</title>
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="myServiceModule">
<div id="simple" ng-controller="MyController as self">
<p>Let's try this simple notify service, injected into the controller...</p>
<input ng-init="message='test'" ng-model="message" >
<button ng-click="callNotify(message);">NOTIFY</button>
<p>(you have to click {{3-self.clickCount}} times more to see an alert)</p>
</div>
<div>You have clicked {{clickCount}} times</div>
</body>
</html>
See it in action on plunker
UPDATE: corrected the trivial errors is html and service code as suggested by #SehaxX
First your HTML is wrong. Your last div is not in the div of Controller, and you dont need the self.
<body ng-app="myServiceModule">
<div id="simple" ng-controller="MyController">
<p>Let's try this simple notify service, injected into the controller...</p>
<input ng-init="message='test'" ng-model="message" >
<button ng-click="callNotify(message);">NOTIFY</button>
<p>(you have to click {{3-self.clickCount}} times more to see an alert)</p>
<div>You have clicked {{clickCount}} times</div>
</div>
</body>
Also in your service you are missing return:
clickCount: function() {
clickCounter = msgs.length;
$log.debug("You are clicking, click count is now", clickCounter);
return clickCounter;
},
And in your controller you only once call the notify.clickCount() so you need to add it to the method:
$scope.callNotify = function(msg) {
notify.push(msg);
$scope.clickCount = notify.clickCount();
$log.debug("Click count is now", $scope.clickCount);
};
Here also a working code pen with "Controller as self" if you want. But then in controller you must use this and not $scope.
Cheers,
I am trying to do something that should be pretty simple. When a user tabs out of an input field, I want to take their value and change the value to contain two decimal places for each number even .00
I have a working plunkr
Here is the HTML
<input type="text" class="form-control" only-digits ng-blur="vm.cleanNumbers(vm.order.frameInformation.A)" ng-model="vm.order.frameInformation.A">
The controller is getting called and the value is changed but the input never reflects the change
function cleanNumbers(value) {
if (value !== 0) {
var hasDecimal = value.indexOf('.') > -1;
value = value.replace('$', '');
value = value.replace(/[,]+/g, '');
value = parseFloat(value);
if (isNaN(value)) {
return 0;
}
value = value.toFixed(2);
}
}
In the plunkr I'm logging the values and seeing what I would hope for the input to update with.
Here is your required answer.
The first issue is to use the controller as Syntax,
ng-controller="test as vm"
Since you are converting the value to Float and trying to display it in the text field,
you are getting the same value since the text value of a float is same as the text.
You have to convert the float back to string to display as you like.
Here is the revised code,
// Code goes here
(function () {
'use strict';
angular
.module('admin', [])
.controller('test', test);
test.$inject = ['$log'];
function test($log) {
$log.debug('controller loaded');
/*jshint validthis: true */
let vm = this;
vm.order = {};
vm.cleanNumbers = cleanNumbers;
function cleanNumbers(test) {
$log.debug(test);
let value = vm.order[test];
if (value != 0 && value != undefined) {
var hasDecimal = value.indexOf('.') > -1;
value = value.replace('$', '');
value = value.replace(/[,]+/g, '');
value = parseFloat(value);
if (isNaN(value)) {
return 0;
}
//value = value.toFixed(2);
function toNumberString(num) {
return value.toString() + ".00"
}
vm.order[test] = toNumberString(value);
console.log(value);
console.log(vm.order);
}
}
}
})();
<!DOCTYPE html>
<html ng-app="admin">
<head>
<script data-require="angularjs#1.5.5" data-semver="1.5.5" src="https://code.angularjs.org/1.5.5/angular.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="test as vm">
<div class="col-md-4">
{{vm.order}}
<div class="form-group">
<label class="control-label">A</label>
<input type="text" class="form-control" ng-blur="vm.cleanNumbers('A')" ng-model="vm.order.A" />
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label class="control-label">B</label>
<input type="text" class="form-control" ng-blur="vm.cleanNumbers('B')" ng-model="vm.order.B" />
</div>
</div>
</body>
</html>
PLEASE run above SNIPPET
HERE IS A WORKING DEMO
First of all, I encourage you to use the latest version of AngularJS (1.6.2 for now). There is still some bug fixes and good changes.
Secondly you are using "vm" controller prefix, but you are not saying that to your controller binder. In your index.html(plunkr) this line;
<body ng-controller="test">
Is I believe intended to be;
<body ng-controller="test as vm">
Also, even this is not handling the actual behaviour that you are trying to do, but I'm sure you can figure the rest of it out by yourself.
I am a beginner angularjs user, but i have to learn it for my new job and I thought I could practice a bit. So I did a simple string reverse method and I thought I could make a simple calculator (exactly, only sum). Here is my code. I made 2 modules, 2 controllers and the first one is working fine, but the calculator isn't. However I made a simple site, where only the calc code is, and it works fine and I don't understand why it works, but doesn't work if 2 modules are on the same site.(Yeah, i'm a very beginner). Thank you for your help.
<!DOCTYPE html>
<html lang="en">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"> </script>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div ng-app="MyApp" ng-controller="myController">
<center>
<input type="text" ng-model="myString" placeholder="Enter text"/>
<p>Input: {{myString }}</p>
<p>Filtered input: {{getReverse()}}</p>
</center>
</div>
<br><br>
<center>
<div ng-app="MyCalc" ng-controller="myCalculate">
<input type="text" ng-model="firstNumber"><br>
<input type="text" ng-model="secondNumber"><br>
<p> Result: {{getResult()}}</p>
</div>
</center>
<script>
var reverse = angular.module("MyApp", []);
var calc = angular.module("MyCalc",[]);
reverse.controller('myController',function($scope){
$scope.myString = "";
$scope.getReverse = function(){
return $scope.myString.split("").reverse().join("");
}
});
calc.controller('myCalculate',function($scope){
$scope.firstNumber = 0;
$scope.secondNumber = 0;
$scope.getResult = function(){
return Number($scope.firstNumber)+Number($scope.secondNumber);
}
});
</script>
ng-app directive can be used just one time in page.
only one AngularJS application can be auto-bootstrapped per HTML document. The first ngApp found in the document will be used to define the root element to auto-bootstrap as an application. To run multiple applications in an HTML document you must manually bootstrap them using angular.bootstrap instead. (https://docs.angularjs.org/api/ng/directive/ngApp)
But you can bootstrap manually your app. Affect id on div that contains an angular app and add this to your script (https://plnkr.co/edit/ZTW7mXx3iXm803xdYod1?p=preview):
angular.bootstrap(document.getElementById('reverse'), ['MyApp']);
angular.bootstrap(document.getElementById('calc'), ['MyCalc']);
But I agree with Vikash, create more modules and less app :)
Normally, you should not use 2 angular app in a web page.
If you need to use different module, just make one depend on another.
Let's say your main module is MyApp and you need MyCalc's function, you do it like this (JsFiddle):
var calc = angular.module("MyCalc",[]);
calc.controller('myCalculate',function($scope){
$scope.firstNumber = 0;
$scope.secondNumber = 0;
$scope.getResult = function(){
return Number($scope.firstNumber)+Number($scope.secondNumber);
}
});
// Make MyApp module depend on MyCalc
var reverse = angular.module("MyApp", ["MyCalc"]);
reverse.controller('myController',function($scope){
$scope.myString = "";
$scope.getReverse = function(){
return $scope.myString.split("").reverse().join("");
}
});
And then in the HTML:
<body ng-app="MyApp">
<div ng-controller="myController">
<center>
<input type="text" ng-model="myString" placeholder="Enter text"/>
<p>Input: {{myString }}</p>
<p>Filtered input: {{getReverse()}}</p>
</center>
</div>
<br><br>
<center>
<div ng-controller="myCalculate">
<input type="text" ng-model="firstNumber"><br>
<input type="text" ng-model="secondNumber"><br>
<p> Result: {{getResult()}}</p>
</div>
</center>
</body>
P/s: If you really need to bootstrap 2 angular app in the same web page, you need to bootstrap it manually (JsFiddle):
angular.bootstrap(document.getElementById('calc'), ['MyCalc']);
calc is the id of the element you need to bootstrap the second app on
<div id="calc" ng-controller="myCalculate">
use ng-module instead of ng-app because ng-app can be used with one module in one page.
<div ng-module="MyModuleA">
<h1>Module A</h1>
<div ng-controller="MyControllerA">
{{name}}
</div>
<div ng-module="MyModuleB">
<h1>Just Module B</h1>
<div ng-controller="MyControllerB">
{{name}}
</div>
var moduleA = angular.module("MyModuleA", []);
moduleA.controller("MyControllerA", function($scope) {
$scope.name = "Bob A";
});
var moduleB = angular.module("MyModuleB", []);
moduleB.controller("MyControllerB", function($scope) {
$scope.name = "Steve B";
});
Use angular ng-modules to achieve this
here is the working [link] [1]
[1] http://jsfiddle.net/j5jzsppv/111/
<div ng-modules="MyModuleA, MyModuleB">
<div ng-controller="myController">
<input type="text" ng-model="myString" placeholder="Enter text"/>
{{myString}}
<p>Filtered input: {{getReverse()}}</p>
</div>
<div ng-controller="myCalculate">
<input type="text" ng-model="firstNumber"><br>
<input type="text" ng-model="secondNumber"><br>
<p> Result: {{getResult()}}</p>
</div>
var reverse = angular.module("MyModuleA", []);
var calc = angular.module("MyModuleB", []);
reverse.controller('myController', function ($scope) {
$scope.myString = "";
$scope.getReverse = function () {
return $scope.myString.split("")
.reverse()
.join("");
}
});
calc.controller('myCalculate', function ($scope) {
$scope.firstNumber = 0;
$scope.secondNumber = 0;
$scope.getResult = function () {
return Number($scope.firstNumber) + Number($scope.secondNumber);
}
});
I've got this code:
<html>
<head>
</head>
<div ng-app="" ng-controller="Test">
<input type="text" ng-model="inputty">
<p>{{output}}</p>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<script>
function Test($scope){
if($scope.inputty=="Hello") {
$scope.output="OK!";
} else {
$scope.output="NOT OK!";
}
}
</script>
</html>
But it's not working, the NOT OK! displays. But it's like the if statement can't read from inputty. So it should state OK! when I type Hello in the input box.
You need to add in a watch in your controlller in order to check the value of inputty and inside the watch function have the if loop so that you can change the output scope variable
Code:
function Test($scope) {
$scope.inputty = '';
$scope.$watch('inputty', function () {
if ($scope.inputty == "Hello") {
$scope.output = "OK!";
} else {
$scope.output = "NOT OK!";
}
});
}
Working Fiddle - $watch
Reference for $watch
Alternatively,
You can do it alone in HTML markup using ng-switch
HTML markup
<div ng-app ng-controller="Test">
<input type="text" ng-model="inputty" />
<div ng-switch="inputty">
<p ng-switch-when="Hello">OK!</p>
<p ng-switch-default>NOT OK!</p>
</div>
</div>
Working Fiddle - ng-switch
Reference for ng-switch
If you only change your inputty through textbox, the easiest way is to use ngChange.
<input ng-model='yourName'>
<p>{{yourName}}</p>
when I type some words in the input yourName, the <p> will display what I typed immediately.
===
If I need do some sync in different model,
eg.
<input ng-model='start'>
<input ng-model='end'>
<input ng-model='step'>,default 10.
when I changed the model start to 1, it automatically update the model end to 11,vice versa.
what should I do?
this problem is solved.just add type="number", thanks
<!DOCTYPE html>
<html ng-app>
<head>
<title></title>
<script src="lib/angular/angular.js"></script>
</head>
<body ng-controller='MyController'>
<input type="number" ng-model="start">
<input type="number" ng-model="end">
<input type="number" ng-model="step">
<script>
function MyController($scope){
$scope.$watch('start',function(newStart){
$scope.end = newStart + $scope.step;
console.log(1);
}) ;
$scope.$watch('end',function(newEnd){
$scope.start = newEnd - $scope.step;
console.log(2);
}) ;
$scope.step = 10;
}
</script>
</body>
</html>
In your controller, use a $scope.$watch() to perform behaviour when each property changes.
e.g.
$scope.$watch('dateStart', function (newDateStart) {
if (!newDateStart) return;
$scope.dateEnd = newDateStart;
});
$scope.$watch('dateEnd', function (newDateEnd) {
if (!newDateEnd) return;
$scope.dateStart = newDateEnd;
});
Note that I would recommend that you first check if there is already a value for the other field, or if the user has manually modified it. If so, don't automatically change the other field. Otherwise, you will be forever overwriting what the user chose for the other field.