How to assign a value in angular's $parse - angularjs

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

Related

When and where to use $eval and $parse

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

How to assign object in factory - angularjs

If I assign an object in a factory like this:
$http.get('/api/whatever').success(function(data) {
result = data.obj
});
It gives result a new address and therefore the reference from my controller to the result is broken.
How to assign it then? Value by value works, but seems not the right way. How to watch an object properly?
Basically factory has get and set methods for getting and setting the value in factory object.
Here is the example. Some time you may have to use events after updating the factory object so all others instance have updated value

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.

Injector returns undefined value?

I'm trying to get the service from my legacy code and running into a weird error with injector() returning undefined:
Check this plnkr
Also, I'm trying to set back the new property value back to the service, will that be reflected to the scope without the use of watch?
Thank you very much, any pointer or suggestion is much appreciated.
You're trying to get the element before the DOM has been constructed. It's basically the same issue as running javascript outside of a $(document ).ready(). So this line has no element to get:
var elem = angular.element($('#myCtr'));
Also, by the way, instead of using jQuery, another Angular option for doing the above is:
var elem = angular.element(document.querySelector('#myCtr'))
Angular provides an equivalent to $(document ).ready() called angular.element(document).ready() which we can use.
But you'll also need to grab scope and execute your change within a scope.$apply() so that Angular is aware that you've changed something that it should be aware of.
Combining the two we get:
angular.element(document).ready(function () {
var elem = angular.element($('#myCtr'));
//get the injector.
var injector = elem.injector();
scope= elem.scope();
scope.$apply(function() {
injector.get('cartFactory').cart.quantity = 1;
});
});
updated plnkr

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