Angular expression not updated upon button press - angularjs

I can successfully update an Angular expression immediately but it fails upon a button press. I need a little help here.
Here's the code.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
</head>
<body>
<div ng-app="MyApp">
<div ng-controller="MyController">
<button id="myButton">Press</button>
{{myMessage}}
<script>
function setMessage(msg) {
angular.module('MyApp', [])
.controller('MyController', function($scope) {
$scope.myMessage = msg;
});
}
setMessage("first");
$(document).ready(function() {
$('#myButton').on('click', function( event ){
setMessage("second");
});
});
</script>
</div>
</div>
</body>
</html>
The first call which happens right away correctly updates the expression to "first". However the second call when the button is pressed fails to upate the expression to "second". What am I doing wrong?

First of all, good advice: remove jQuery from the project until you understand well why you should not use jQuery-style development with Angular app. Shortly, Angular has a specific event/parsing/compiling lifecycle that is not the same as just the flow we are used in jQuery projects. Take a look at this thread.
Then what you need to do is to use ngClick directive:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>
<div ng-app="MyApp">
<div ng-controller="MyController">
<button ng-click="setMessage('second')">Press</button>
{{myMessage}}
</div>
</div>
<script>
angular.module('MyApp', [])
.controller('MyController', function($scope) {
$scope.myMessage = 'first';
$scope.setMessage = function(msg) {
$scope.myMessage = msg;
};
});
</script>

Remove the function around your angular module and you should use angular's ng-click directive to update your html on click:
<div ng-app="MyApp">
<div ng-controller="MyController">
<button id="myButton" ng-click="update('second')">Press</button>
{{myMessage}}
<script>
angular.module('MyApp', [])
.controller('MyController', function($scope) {
$scope.myMessage = "first";
$scope.update = function(msg){
$scope.myMessage = msg;
}
});
</script>
</div>
</div>
The documentation for ng-click: https://docs.angularjs.org/api/ng/directive/ngClick

Don't mix jQuery with angularjs, unless is totally needed. See this answer about it
you should use all the events, functions and directives providad by angularjs.
So your coude would look to something like this
<div ng-app="MyApp">
<div ng-controller="MyController">
<button ng-click="setMessage()">Press</button>
{{myMessage}}
<script>
function setMessage(msg) {
angular.module('MyApp', [])
.controller('MyController', function($scope) {
// set the original value for myMessage
$scope.myMessage = "first";
// update with second value
$scope.setMessage = function(){
$scope.myMessage = "second";
}
});
}
</script>
</div>
</div>
Of course you should organize this better, but this is the first approach
The main difference is that if you use the angular events (like ng-click in this case) it will let Angular knows what something has changed and that it has to update/refresh the view.
If you change something with jQuery, unless you force angular to know it (using $scope.$apply()) there is no way that angular knows by itself that the model has changed.

Related

Call angular js function on html tag load

I am trying to call one angular js function using controller. I am using code:
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>DevPortal</title>
<script src="js/angular.min.js"></script>
<script src="js/controllers/app.js"></script>
</head>
<body ng-app="devportal">
<div ng-include="'templates/login_menu.html'"></div>
</body>
</html>
app.js
var app = angular.module('devportal', []);
app.controller('AppController', function($scope, $http) {
return{
getuserloginmenu : function(){$http.get('/getuserloginmenu').then(function(response){$scope.loginmenu=response.data;})},
getuserloginmenu1 : function(){$http.get('/getuserloginmenu1').then(function(response){$scope.loginmenu1=response.data;})}
};
});
login_menu.html
<div ng-controller="AppController as ctrl">
<div on-init="ctrl.getuserloginmenu()">
<p ng-repeat="menu in loginmenu">{{menu}}</p>
</div>
</div>
My rest service is working properly and returns String array. I am not able to call/get the rest service data in html.
Your code seems legit, the only thing making noise (at least for me) is the on-init you added to call the function. I think that's the problem.
Try
<div ng-controller="AppController as ctrl">
<div ng-init="ctrl.getuserloginmenu()">
<p ng-repeat="menu in loginmenu">{{menu}}</p>
</div>
</div>
And maybe.. To keep it clean: Change the syntax of the controller (even if it works)
var app = angular.module('devportal', []);
app.controller('AppController', function($scope, $http) {
$scope.getuserloginmenu = function(){$http.get('/getuserloginmenu').then(function(response){$scope.loginmenu=response.data;})};
$scope.getuserloginmenu1 = function(){$http.get('/getuserloginmenu1').then(function(response){$scope.loginmenu1=response.data;})};
});
Edit:
That's a missuse of ng-init. I'll leave the documentation of Angular for that matter
https://www.w3schools.com/angular/ng_ng-init.asp
But shortly, you want $scope.loginmenu to populate. You don't need to wait until the div loads. You can populate $scope.loginmenu right away when the controller inits.
View
<div ng-controller="AppController as ctrl">
<div>
<p ng-repeat="menu in loginmenu">{{menu}}</p>
</div>
</div>
Controller
var app = angular.module('devportal', []);
app.controller('AppController', function($scope, $http) {
$scope.getuserloginmenu = function(){$http.get('/getuserloginmenu').then(function(response){$scope.loginmenu=response.data;})};
$scope.getuserloginmenu1 = function(){$http.get('/getuserloginmenu1').then(function(response){$scope.loginmenu1=response.data;})};
$scope.getuserloginmenu();
});

angular : duplicate in calling controller's function

I have following angular code
<!DOCTYPE html>
<html>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
Test : {{mytest()}}
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.name= "John ";
$scope.mytest = function () {
console.log('my test');
return 'something';
};
});
</script>
</body>
</html>
For more detail, please refer to http://plnkr.co/edit/UIu50AOLMwKIJnAphIB5
Problem: when view in Chrome browser 'Inspect Element' console, the function 'my test' is called 3 times! Why ?
Because you've asked angular to do that. This expression
{{mytest()}}
Is in fact instruction:
"angular, do check if the result value of mytest() is not changing. And do that regularly".
And angular is checking that few times, to be sure that it is not changed. And later, in some other digest it will do the same again
so, rather trigger that method once, and let angular to watch the resulting expression, like with a name above
{{name}}

AngularJS: Cannot find the reason for the following error: [ng:areq] Argument 'MyCtrl' is not a function, got undefined

I'm new to AngularJS, just started to learn it like 30 mins ago and trying to practice with some basics to get going. I saw the similar posts with the same error, but could not find the solution.
I have a simple html:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="../Scripts/angular.js"></script>
<script src="../Scripts/app.js"></script>
</head>
<body ng-app>
<div ng-controller="MyCtrl">
<button ng-click="toggle()">Toggle</button>
<p ng-show="visible">Hello World!</p>
</div>
</body>
</html>
And controller in app.js file:
function MyCtrl($scope) {
$scope.visible = true;
$scope.toggle = function () {
$scope.visible = !$scope.visible;
};
}
When loading the page I have the error in a question.
What can be wrong with that?
You need to define angular module first then add that components like controller, directive, factory, etc. in it, then you need to add that module inside the ng-app directive.
Markup
<body ng-app="myApp">
<div ng-controller="MyCtrl">
<button ng-click="toggle()">Toggle</button>
<p ng-show="visible">Hello World!</p>
</div>
</body>
Code
angular.module('myApp', [])
.controller('MyCtrl', MyCtrl)
function MyCtrl($scope) {
$scope.visible = true;
$scope.toggle = function () {
$scope.visible = !$scope.visible;
};
};
Demo here

AngularJS : How to get a sub-total from my directive using ng-repeat?

I have a situation where I'm using an ng-repeat to display a directive, and this directive is responsible for calculating a sub-total and using 2-way binding to add that sub-total to my total.
However, by using the ng-repeat, it's adding to the scope of the ng-repeat instead of my controller. How can I get this to work correctly?
Edit: I figured out a solution, but not sure if it's the best way to do it...
I changed:
<div ng-repeat='item in myArray'>
<add-it-up sub-total='total1'></add-it-up>
</div>
to
<div ng-repeat='item in myArray'>
<add-it-up sub-total='$parent.total1'></add-it-up>
</div>
and it's working. Is there a better way to do this?
Plunker: http://plnkr.co/edit/lqh0z93yc5Q5E2gNBdtG?p=preview
<!DOCTYPE html>
<html ng-app='testApp'>
<head>
<script data-require="angular.js#1.3.15" data-semver="1.3.15" src="https://code.angularjs.org/1.3.15/angular.js"></script>
</head>
<body ng-controller='TestCtrl'>
<!-- This doesn't work -->
<div ng-repeat='item in myArray'>
<add-it-up sub-total='total1'></add-it-up>
</div>
{{total1}}
<br />
<!-- This does work -->
<add-it-up sub-total='total2'></add-it-up>
<add-it-up sub-total='total2'></add-it-up>
<add-it-up sub-total='total2'></add-it-up>
{{total2}}
<script>
var app = angular.module('testApp', []);
app.controller('TestCtrl', ['$scope', function($scope) {
$scope.myArray = [0, 1, 2];
$scope.total1 = 0;
$scope.total2 = 0;
}])
app.directive("addItUp", function () {
return {
restrict: 'E',
scope: {
subTotal: "="
},
controller: ['$scope', '$timeout', function ($scope, $timeout) {
$timeout(function() {
console.log($scope.subTotal)
$scope.subTotal += 5;
console.log($scope.subTotal)
})
}]
}
})
</script>
</body>
</html>
You have to add an object to your $scope containing the total1. Otherwise this property gets overwritten by the ng-repeat sub-scopes:
$scope.totals = {
total1: 0,
total2: 0
};
Have a look at this updated plnkr. For more information visit Understanding Scopes.

Why is ng-bind-html not displaying anything?

I am displaying a string that has HTML code in it:
<div style="font-size: 14px" ng-bind="currentBook.description"></div>
put it displays the HTML code instead of interpreting the elements:
When I use ng-bind and ng-bind-unsafe, it shows nothing.
How can I get the HTML to be parsed?
Addendum
I added a reference to sanitize but ng-bind and ng-bind-unsafe still show nothing:
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular-route.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular-sanitize.js"></script>
Ok, I added the ngSanitize var app = angular.module('app', ['ngSanitize']); and now it works.
It looks like you missed ngSanitize please see demo below
You can find more here
https://docs.angularjs.org/api/ngSanitize/service/$sanitize
var app = angular.module('app', ['ngSanitize']);
app.controller('firstCtrl', function($scope, $sce) {
$scope.currentBook = {
description: "<p>some description</p>"
};
});
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular-sanitize.js"></script>
<body ng-app="app">
<div ng-controller="firstCtrl">
<div style="font-size: 14px" ng-bind-html="currentBook.description"></div>
</div>
</body>
call apply
$scope.$apply(function () {
$scope.currentBook.description = $sce.trustAsHtml(html);
});

Resources