How to assign object in factory - angularjs - 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

Related

How to handle $digest triggered by $http

I have been struggling a long way in a issue, wherein I need to update a parent obj from directive scope. I need to fetch some data using $http and fit this data against a property in original parent Obj.
However, after doing this, the view gets updated but somehow the model binded to these view become undefined. Since the view are updated with new data, somehow the models are becoming undefined after that.
Only now I came to know that, $http triggers a $digest, so I think that is the cause of my issue.
What can I do to avoid my models becoming undefined and the fetched values to remain intact in original object.
Just to make things clear, before I attach a wrking plnkr. here is what I mean:
I have a obj $scope.Obj. I have binded the input fields in directive template with this object using 2 way binding like
<input ng-model = Obj.something.something2[$index]/>
Now say I made a API call and update my something2 in $scope.Obj as:
$scope.Obj.something.something2 = APIResponse.something3
The values from new object something3 are visible on UI, but in backend after this
$scope.Obj.something.something2[$index]
becomes undefined.
Pls suggest possible reasons for this...
The other models are becoming undefined because you are replacing the object. Instead you should use angular.extend.
angular.extend($scope.Obj.something.something2, APIResponse.something3);
For more information see the AngularJS angular.extend API Reference.

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

How to preserve an object initial data?

I am facing some weird behavior with AngularJS in preserving a variable data which got binded to a from using scope, let me explain my scenario.
I have a form whose field values are initially served form controller through a scope variable, I need to compare the updated values with those initial values while saving, so I kept the initial data in a variable and assigned that variable to scope.
Whenever I change the form fields, controller variable data also getting updated along with scope variable. I am not sure whether this is the correct behavior or not, I guess only scope should get updated.
Anyone please suggest the correct behavior and how to solve this issue if that's the correct behavior.
JS Bin: http://jsbin.com/kakapinuhe/edit?html,js,console,output
You will get to know the problem easily by looking at the above JSBin link, let me know if needed any clarification.
Thanks,
Siva
Yes, that is the expected behavior of javascript. When you assign:
$scope.formData = initData;
you are NOT making a copy of your initData variable. Instead, your formData is refering to same memory space as your initData. in short, they are referring to the same data.. so even if formData change.. your initData is lost.
You can fix this by using angular.copy():
$scope.formData = angular.copy(initData);
Here is the modified JSbin: http://jsbin.com/yoviyesero/edit?html,js,console,output
Use angular.copy
Reason: When you write
$scope.formData = initData.
You are creating a reference to same object initData. So any changes in $scope.formData will reflect in object too. Using angular.copy will create a deep copy of source without any references.

$watchCollection on an array of js objects in an Angular Controller requires an anonymous function?

I have a simple js array being retrieved by an angular factory, injected into a control, watched, then displayed in a table using ng-repeat from within a view state managed by ui-router.
Initially I attempted to subscribe to this array using $watchCollection...
self.$watchCollection( self.Data, function(newData, oldData){
self.total = newData.length;
});
However this was only running when I initially load the app. I found that the only way to subscribe to the running collection was to use an anonymous function returning the array in question.
self.$watchCollection( function() { return self.Data }, function(newData, oldData){
self.totalWatchedWithAnonFunc = newData.length;
})
View this all in http://plnkr.co/edit/L7mycl
From everything I read, all I should have needed to do for a valid subscription was to pass in the array itself and not an anonymous function that returns the array.
The reason I included ui-router is because my actual application is using it heavily and I wanted to mock up my environment as closely as possible to how I've got things set up.
What am I not understanding? Could I be doing something differently?
Thanks.
Are you looking for self.$watchCollection("Data", ...) instead of self.$watchCollection(self.Data, ...)? Try it out! See the docs to see why: the first argument is a string evaluated on the scope, or a function taking a scope that returns something you want to watch.

How to log/ inspect a $resource in a $scope variable in AngularJS controller?

In a controller, when I get a resource from a service
$scope.myVariable = MyObject.get($scope.id);
then myVariable is not defined as MyObject since it will be resolved later. Is there a way to inspect the variable in the controller (not in the service), for example for debugging or logging? Basically I am looking for something like
console.log("myVariable now has property "+ $scope.myVariable.myProperty);
From AngularJS Doc to $resource, you can read that:
It is important to realize that invoking a $resource object method
immediately returns an empty reference.
Once the data is returned from the server the existing reference is
populated with the actual data. This is a useful trick since usually
the resource is assigned to a model which is then rendered by the
view. Having an empty object results in no rendering, once the data
arrives from the server then the object is populated with the data and
the view automatically re-renders itself showing the new data. This
means that in most case one never has to write a callback function for
the action methods.
But, if you need to print the value of $scope.myVariable once it gets populated, you will have to define a callback function:
$scope.myVariable = MyObject.get($scope.id, function(myVar){
// From now, myVar == $scope.myVariable
console.log("myVariable now has property "+ myVar.myProperty);
});

Resources