Input will not update onblur with ng-blur - angularjs

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.

Related

AngularJS code is not running and getting no error message when inspected

When I inspect it, there are no error and it's returning nothing so, apparently not running :
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles/bootstrap.min.css">
<style>
.message {
font-size: 1.3em;
font-weight: bold;
}
</style>
<script src="angular.min.js"></script>
</head>
<body ng-app='LunchChecker'>
<div class="container" ng-controller='MyLunchCheckController'>
<h1>Lunch Checker</h1>
<div class="form-group">
<input id="lunch-menu" type="text" placeholder="list comma separated dishes
you usually have for lunch" class="form-control" ng-model='MenuInput'>
</div>
<div class="form-group">
<button class="btn btn-default" ng-click="checkInput()">
Check If Too Much</button>
</div>
<div class="form-group message" {{checkInput()}}>
<!-- Your message can go here. -->
</div>
</div>
<script src="app.js"></script>
</body>
</html>
Below is the app.js script for the above view the purpose of the code is to return either msg1 if the input is less than 3 menu or msg2 if the input is more than 3 :
(function() {
'use strict';
angular.module('LunchChecker', [])
.controller('MyLunchCheckController', MyLunchCheckController);
MyLunchCheckController.$inject = ['$scope'];
function MyLunchCheckController($scope) {
$scope.MenuInput = [].slice;
$scope.values = new Array($scope.MenuInput.length);
$scope.msg1 = "Enjoy!";
$scope.msg2 = "Too much!";
//fucntion for the button to check the user input menu-list
$scope.checkInput = function() {
for (var i = 0; i < $scope.values; i++) {
if ($scope.values <= 3) {
return $scope.msg1;
} else {
return $scope.msg2;
}
}
};
}
})();
When I try to reflect your code, I am getting function slice() { [native code] } inside the text box. As you have initialised the value of MenuInput as [].slice.
So to improve and compare the code
'use strict';
angular.module('LunchChecker', [])
.controller('MyLunchCheckController', ['$scope', function($scope) {
$scope.msg1 = "Enjoy!";
$scope.msg2 = "Too much!";
$scope.checkInput = function() {
if($scope.MenuInput.split(",").length <= 3) {
$scope.values = $scope.msg1;
} else{
$scope.values = $scope.msg2;
}
};
}]);
It will print the message in the console according to the length you compare. For displaying the message you can write like:
<div class="form-group message" {{checkInput()}}>
to
<div class="form-group message"> {{values}}</div>

AngularJS function if else

I am trying to do a function inside of a controller that uses an if else to change the return. And it works until I change the drop down, and then stops working completely. It does not seem to be working, not sure if I am doing something wrong, or you just cannot do this type of function. Any help would be appreciated.
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular-sanitize.js"></script>
<script>
var app = angular.module('newApp', ['ngSanitize']);
app.controller('player1ctrl', function ($scope) {
$scope.playerName = "Hero";
$scope.playerCard = "A<br />♠";
$scope.color = function () {
//return $scope.playerName;
var arr = $scope.playerCard.split("<br />");
var rtn = "";
if (arr[1] == "♠" || arr[1] == "♣") {
return "Black";
}
else {
return "Red";
}
};
});
</script>
<title>test ngbindhtml</title>
<meta charset="utf-8" />
</head>
<body ng-app="newApp">
<div ng-controller="player1ctrl">
Card selected: <p ng-bind-html="playerCard"></p>
Suit Color: {{color()}}
<select name="playerCard" ng-model="playerCard">
<option value="2<br /> &spades;">2 ♠</option>
<option value="3<br /> &spades;">3 ♠</option>
<option value="4<br /> &hearts;">4 ♥</option>
</select>
</div>
</body>
</html>
First of all - You have space in ♠:
if(arr[1] == " ♠" || arr[1] == " ♣")
Second - You need use:
ng-bind-html-unsafe="playerCard"
in Your template or use trustAsHtml in controller;
Plunker
You cannot bind an HTML string without "trusting" it in Angular. Your "playerCard" variable, with the <br /> is causing the issue. You need to inject $sce into your controller and then call the trustAsHtml function:
...
app.controller('player1ctrl', function ($scope, $sce) {
...
$scope.playerCard = $sce.trustAHtml("A<br />♠");
Doing this should allow you to still use [the correct] ng-bind-html like you currently are. You can also turn this into a directive quite easily.

Angularjs action on click of button

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.

how to sync different model in angular

<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.

Angular - default value for model

Say I have some html as follows:
<html>
<head> angular etc. </head>
<body ng-app>
<div ng-controller="MyCtrl">
<input ng-model="weight" type="number" min="{{minWeight}}" max="{{maxWeight}}">
<p>{{weight}}</p>
</div>
</body>
</html>
and the following controller:
function MyCtrl($scope){
$scope.weight = 200;
$scope.minWeight = 100.0;
$scope.maxWeight = 300.0;
}
The "min" and "max" will show the user their input is bad, and if I hard code them to say, 100 and 300, it will make sure the value is never bound to the model at all (why isn't the behavior the same??). What I'd like to do is only actually change the "weight" if the value meets the input requirements. Any thoughts?
I don't fully understand what are you trying to do.
HTML:
<html>
<head> angular etc. </head>
<body ng-app="MyApp">
<div ng-controller="MyCtrl">
<input ng-model="weight" type="number" min="{{minWeight}}" max="{{maxWeight}}">
<p>{{weight}}</p>
</div>
</body>
</html>
Angular: [Edit]
var app = angular.module('myApp', []);
app.controller('MyCtrl', ['$scope', function MyCtrl($scope){
$scope.weight = 200;
$scope.minWeight = 100.0;
$scope.maxWeight = 300.0;
$scope.$watch('weight', function (newValue, oldValue) {
if(typeof newValue === 'number') {
if(newValue > $scope.maxWeight || newValue < $scope.minWeight) {
$scope.weight = oldValue;
}
}
});
}]);
But here is an example I made in jsFiddle. I hope this was a solution you were looking for.
[Edit]
http://jsfiddle.net/migontech/jfDd2/1/
[Edit 2]
I have made a directive that does delayed validation of your input field.
And if it is incorrect then it sets it back to last correct value.
This is totally basic. You can extend it to say if it is less then allowed use Min value, if it is more then allowed use Max value it is all up to you. You can change directive as you like.
http://jsfiddle.net/migontech/jfDd2/2/
If you have any questions let me know.

Resources