When and where to use $eval and $parse - angularjs

When and where to use $eval and $parse in angularjs.
eReaderBook.controller("mainCtrl",function($scope){
$scope.test = "asdasd";
var s = "{{test}}";
console.log($scope.$eval("s"))
})
why console.log returns undefined.

You are getting undefined for the following reason.
$eval method works on scope variable. Here your variable s is just a normal javascript variable. But if you try to log 'test' as follows. You will see the proper value is being printed.
console.log($scope.$eval("test"))
If you try without quote as follows
$scope.$eval(s)
Then you will find
Syntax Error: Token '{' invalid key
because value of s is {{test}}. So then eval will try to find the value from the scope as $scope.{{test}} which is invalid and has syntax error.
More over $scope.$eval('a+b') means $scope.a+$scope.b
So in easy words those expression which you can write inside binding block {{ expression }} of angular, you can also write inside $eval method as string.
{{WHAT EVER YOU CAN WRITE HERE}}
$scope.$eval('YOU CAN WRITE HERE ALSO');

eReaderBook.controller("mainCtrl",function($scope){
$scope.test = "asdasd";
var s = "test";
console.log($scope.$eval(s))
})
$scope.$eval, unlike eval() already expects AngularJS's recognized format.
Also don't need the " in eval

$parse is an Angular service which converts an expression into a function. The function can then be invoked and passed a context (usually scope) in order to retrieve the expression's value.
$eval is a scope method which executes an expression on the current scope and returns the result.
For more information refer:
http://ng.malsup.com/#!/$parse-and-$eval
https://docs.angularjs.org/api/ng/service/$parse

Related

AngularJS: is 0 == 2? [duplicate]

This question already has answers here:
How to parseInt in Angular.js
(7 answers)
Closed 6 years ago.
I am scratching my head here. I am using angularJS and trying to use the expression that contains call to parseInt.
{{0 == 2}}
...prints out false as expected.)
However, when I am trying:
{{parseInt(0) == parseInt(2)}}
... it prints out... true !
How can this be possible?
Angular does not use JavaScript's eval() to evaluate expressions.
Instead Angular's $parse service processes these expressions.
Angular expressions do not have access to global variables like
window, document or location. This restriction is intentional. It
prevents accidental access to the global state – a common source of
subtle bugs.
Refer
In your html
Both parseInt(0) and parseInt(2) are undefined in your html.
So {{undefined==undefined}} is true.Beacause parseInt is a Javascript function.So you cant access the parseInt function in side {{}}. [Here parseInt is not a scope variable]
Solution
If you wish to do this,
define parseInt in your controller,
$scope.parseInt = parseInt;
Then you can use the parseInt method in your html
That's because parseInt is not defined in your scope.
http://jsfiddle.net/halirgb/Lvc0u55v/
You can't execute regular JS in an angular expression. Your expressions will be evaluated against the current scope. So, parseInt is undefined in the current scope.
If you set parseInt as a function reference, it will work.
$scope.parseInt = parseInt;
This is because the view is attached to the controller via scope.
So whatever we write in view either a variable or a function or anything it's rendered by appending $scope in front of it.
eg.
a is rendered as $scope.a in the view
So when we write parseInt, its rendered by $scope.parseInt which is not defined.
FIX- define $scope.parseInt = parseInt in the controller attached to the particular view
You have comparing both undefined values so result will be true.
You cannot call a javascript method(parseInt) via angular directives(ng-blur,ng-change,..) either you can achieve by making angular functions.
Solution 1:
{{0*1 == 2*1}}
Just do a trick to convert to Integer by multiply with 1 (0*1 = 0, 2*1 =1).
Solution 2:
{{parseInt(0) == parseInt(2)}}
Controller:
// To Convert specific format
$scope.parseInt = funtion(value){
return parseInt(value,10);
}
or
$scope.parseInt = parseInt;
reference here

How to assign a value in angular's $parse

I have a string reference to one of my scope values like this:
var reference_string = "form.name";
And I want to assign a value to the object it is referencing:
$scope.form.name = 'newvalue';
Looking around, I found 2 possible solutions: using plain JS or using the angular $parse function.
However, it seems like the $parse function only returns the value. Can I make it so that I can assign a new value?
ie. I want to do something like
var reference_string = "form.name";
var reference = getReference($scope, reference_string); // ideally using an angular in-built function like $parse
reference = 'newvalue'; // should have the same effect as $scope.form.name = 'newvalue';
The object returned by $parse has an assign() method for setting values.
var getter = $parse(reference_string);
getter.assign($scope, 'newValue');
Plunker demo ~ http://plnkr.co/edit/RlhXRpJvQ69ZdEkstyq8?p=preview
$parse is an Angular service which converts an expression into a function. The function can then be invoked and passed a context (usually scope) in order to retrieve the expression's value.
In addition, if the expression is assignable the returned function will have an assign property. The assign property is a function that can be used to change the expression's value on the given context.
enter link description here

ng-book examples not working as expected

I'm currently reading through ng-book for angular js and have come accross two example pieces of code.
The first deals with the $parse service and can be found here: http://jsbin.com/UWuLALOf/1/edit
The second deals with $interpolate and can be found here: http://jsbin.com/oDeFuCAW/1/edit
Neither of these are working as expected (I think). They should be updating the view live. I've tried creating the first example locally but I get the same result. I thought maybe it was due to the version of angular but since it's using a specific version from the google api's this shouldn't be an issue. I'd like to figure out exactly what the parse and interpolate services are doing here so any ideas greatly appreciated.
Thanks
C
Instead of passing newVal param to $parse function you should pass an expression 'expr'
$scope.$watch('expr', function(newVal, oldVal, scope) {
if (newVal !== oldVal) {
// Let's set up our parseFun with the expression
var parseFun = $parse('expr');
// Get the value of the parsed expression, set it on the scope for output
scope.parsedExpr = parseFun(scope);
}
});
that's beacues the version of angular which you attached to site is not stable version , use this
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular.min.js"></script>
but nevertheless code are not working as expected
The code is working as expected but most likely you are not expecting what you should :)
Let's take one at a time:
$scope.$watch('expr', function(newVal, oldVal, scope) {
if (newVal !== oldVal) {
// Let's set up our parseFun with the expression
var parseFun = $parse(newVal);
// Get the value of the parsed expression, set it on the scope for output
scope.parsedExpr = parseFun(scope);
}
});
The $scope.$watch is setup and is monitoring changes tn the expr variable, which is tied with the input value via ng-model
If you change the expr value in the input, it is send to $parse for evaluation (1+1 should present 2, name should present {"name":"Ari Lerner"} in this case).
$parse will convert a string expression to a function, so having this in mind you should know what to expect.
In the second example, when the body part is changed via the textarea, the template is rendered via $interpolate which will evaluate anything inside {{ }} and then render the html.

Difference between two ways of applying $watch in angularjs

I am using service to communicate between the controllers, while using $watch in my controller, i am able to use it in two ways
service.coffee
myContent = null
getContent = ->
return myContent
setContent = (data) ->
myContent = data
return myContent
my controller:
$scope.test = myService
$scope.$watch "test.getContent()", ->
if $scope.test.getContent() is 'data'
console.log 'yes'
Also,
$scope.$watch (->
test.getContent()
), (value) ->
if value is 'data'
console.log 'yes'
Both gives the expected result, but i would like to know whats the difference between the two methods and in which scenerio we should use the same
Consult the Angular Documentation on $rootScope for a more in-depth answer.
$scope.$watch() takes three arguments, where watchExpression is the first. watchExpression can be either a string or a function. If it is a string, it is evaluated in the $scope in question.
This allows us to easily listen to values on the scope:
$scope.someValue = 2;
$scope.$watch('someValue', function(someValue) {
// some function
});
In your case, you could simply pass it the function:
$scope.$watch($scope.test.getContent, ...);
To sum up, pass a function when the result of it is what you want to watch, or pass an expression if that makes more sense (in most cases, it probably will). It makes little sense to pass a string expression evaluating to the result of some function already available, especially taking into account that the expression would have to be parsed, causing an extra overhead.
No difference actually. The first parameter of $watch function is either a String or a function. If you pass a string as the first parameter for $watch, Angular will automatically parse the string into a function taking the $scope as the function context.
So you can take the following piece of code
$scope.$watch("book", function(){...});
as
$scope.$watch(function(){return $scope.book;}, function(){...});
They are internal equivalent.

Why Angular Js Parameter of a Watch Function Should Be a Scope Variable?

$scope.myFunc = function(privilege){
$scope.check = function(privilege){
return ...
};
$scope.$watch('check(privilege)',function(val){
...
}
}
My privilege variable becomes undefined at every watch check(which must not be)? Why I should define it scope variable or do I miss anything with Angular Js?
The first parameter of the $watch method (the "watchExpression") can be either an Angular string expression (that is evaluated against the $scope), or a function, which is called with $scope as the first parameter. There is no way to pass privilege as the first argument to a watchExpression that is a function.
You could create a closure, if you don't want to store the privilege value on the $scope. See Vojta's fiddle for an example.
See also https://groups.google.com/forum/#!msg/angular/UJRxn_Y0Dd4/9ha38PC3PCwJ

Resources