In my AngularJS project, I am not able to share data of copied objects across different controllers.
I am able to share data properly if I set the properties in code but if I copy the object then it does not appear to work.
In the code block at the JSFiddle, you will see that I have two objects User and OriginalUser.
As soon as the FirstCtrl is loaded, I copy the User object to the OriginalUser object.
You will see that while the value assigned to User object in FirstCtrlis accessible in SecondCtrl but the data of OriginalUser is accessible only in the FirstCtrl.
You can see the code in action at Code Sample at JSFiddle
This is because you are not update OriginalUser data but you create a new variable using angular.copy function.
What you are looking for is angular.extend which will copy user properties to your original user. Now, both controllers use the same object instance.
Your first controller:
function FirstCtrl($scope,User, OriginalUser){
$scope.user = User;
$scope.o_user = angular.extend(OriginalUser, $scope.user);
}
Your fiddle is up to date.
Related
I am absolutly new in AngularJS and I am studying it on a tutorial. I have a doubt related the use of the factory in Angular.
I know that a factory is a pattern used to create objects on request.
So in the example there is the following code:
// Creates values or objects on demand
angular.module("myApp") // Get the "myApp" module created into the root.js file (into this module is injected the "serviceModule" service
.value("testValue", "AngularJS Udemy")
// Define a factory named "courseFactory" in which is injected the testValue
.factory("courseFactory", function(testValue) {
// The factory create a "courseFactory" JSON object;
var courseFactory = {
'courseName': testValue, // Injected value
'author': 'Tuna Tore',
getCourse: function(){ // A function is a valid field of a JSON object
alert('Course: ' + this.courseName); // Also the call of another function
}
};
return courseFactory; // Return the created JSON object
})
// Controller named "factoryController" in which is injected the $scope service and the "courseFactory" factory:
.controller("factoryController", function($scope, courseFactory) {
alert(courseFactory.courseName); // When the view is shown first show a popupr retrieving the courseName form the factory
$scope.courseName = courseFactory.courseName;
console.log(courseFactory.courseName);
courseFactory.getCourse(); // Cause the second alert message
});
And this is the code, associated to this factoryController controller, inside the HTML page:
<div ng-controller="factoryController">
{{ courseName }}
</div>
So it is pretty clear for me that:
The factoryController use the courseFactory factory because is is injected
The first thing that happen when I open the page is that an alert mesage is shown because it is called the:
alert(courseFactory.courseName);
Then put into the $scope.courseName property (inside the $scope object) the value of the **courseName field of the courseFactory JSON object).
And here my first doubt. I have that the factory is defined by:
.factory("courseFactory", function(testValue)
that I think it means (correct me if I am doing wrong assertion) that my factory is named courseFactory and basically is a function that retutn the courseFactory JSON object.
So this is creating me some confusion (I came from Java) because in Java I call a factory class and I obtain an instance of an object created by the factory. But in this case it seems to me that doing:
$scope.courseName = courseFactory.courseName;
it seems to me that the courseName is retrieved directly by the courseFactory JSON object and I am not using the courseFactory.
How it exactly works? Why I am not calling some getter on the factory? (or something like this)
To simplify things There are two known methods to create functions ( and methods ) that are Usable among all states ( consider it as creating a function in global scope ) , these are factory and service.
you may want to read this first Factory vs Service
it seems to me that the courseName is retrieved directly by the
courseFactory JSON object and I am not using the courseFactory.
Actually this is partially true , as Angular use DI concept ( depency injection ) , you will have to inject your factory ( which by default returns an object , and corresponding functions as attributes ) , case you don't ; you will not be able to use your factory object methods.
Angular is not magic , it is just most people don't realize the most basic concepts of JavaScript , specially Developers coming from different programming environment such as C# , C++ , or Java
Easy.
When you return the courseFactory object in the factory statement, the injected courseFactory in the controller becomes THAT object. Therefore, when you do $scope.courseName = courseFactory.courseName; in the controller, you are actually referencing to the returned object that is injected into the controller as courseFactory. So you don't need a getter, because the courseFactory in your controller is already the object. You can do a console.log(courseFactory); in your controller to see what the courseFactory is. Hope this helps.
When an Angular application starts with a given application module,
Angular creates a new instance of injector, which in turn creates a
registry of recipes as a union of all recipes defined in the core "ng"
module, application module and its dependencies. The injector then
consults the recipe registry when it needs to create an object for
your application.
Ref. https://docs.angularjs.org/guide/providers
Factory is a Singleton service. When you inject the factory in the controller or in any other factory, u get the exact json object which u have defined. It will not create any new instance every time you call it. Factory is initialized only once
I currently have an application with a rather complex wizard to create a data record. The wizard consists of 3 steps, each associated with a nested view and a controller. Only the data record itself is shared among all three scopes and each controller contributes additional data to the main record.
But they also have scope specific data, that will be used to render additional fields which are only relevant to that nested scope.
I want to be able to go back and forth between the wizard steps but currently it looks like the nested scopes get discarded as soon as I move on to another nested view. I looked up the scope lifecycle in the developer guide: https://docs.angularjs.org/guide/scope#scope-life-cycle
But I does not really tell me how the scope lifecycle applies to nested scopes and how I can prevent these scopes from being discarded. Of course I could move all the data of the nested scopes into the parent scope, but to me that would just feel like a workaround, because actually that data is only relevant to the individual scopes.
I'll try to give a short example:
angular.module('app').controller('ParentCtrl', function ($scope) {
...
$scope.dataRecord = {};
}
angular.module('app').controller('Child1Ctrl', function ($scope) {
...
$scope.dataRecord.test = 'a';
$scope.childScope1SpecificData = '123';
}
angular.module('app').controller('Child2Ctrl', function ($scope) {
...
$scope.dataRecord.test2 = 'b';
$scope.childScope2SpecificData = '456';
}
When I now switch back and forth between the two childscopes, the dataRecord will be adjusted properly, but changes to childScope1SpecificData (via an input field from the template) will be discarded as soon as I switch to Child2Ctrl and back.
Is there a way to persist this data which switching the scope or is it meant to be discarded and I am simply using it wrong?
Thanks
EDIT:
Ok I looked into the factory approach. Maybe to make it more plastic: The additional data, that belongs to each child scope, is a fileuploader with its associated upload queue. Only in a later validation step these pictures actually become part of the datarecord, but until then I don't want the uploaded images to get lost upon switching views.
So what I could do is to externalize the whole fileupload logic into a factory that returns fileuploaders associated to IDs. Whenever a child scope requests the same id the factory will return the same fileuploader. Different Ids will return different uploaders or new ones. That would pretty much solve the problem but would also mean that the data never gets discarded at all unless I really close the browser, because the factory now is absolutely independent of any scope. Since I only want to retain the data in the context of that wizard, I want the data to be discarded, as soon as I leave the wizard.
So after having looked into these other approaches, it seems like I have to go with the original idea: I have to attach the uploaders to the parent scope. So they will continue to exist when switching to other child views, but they will also be discarded as soon as I leave the wizard.
I hope that was correctly summarized
If you are using 'controller as' syntax, you can use this variant.
angular.module('app').controller('ParentCtrl', function ($scope) {
...
$scope.dataRecord = {};
}
angular.module('app').controller('Child1Ctrl', function ($scope) {
...
$scope.ParentCtrl.dataRecord.test = 'a';
$scope.ParentCtrl.childScope1SpecificData = '123';
}
angular.module('app').controller('Child2Ctrl', function ($scope) {
...
$scope.ParentCtrl.dataRecord.test2 = 'b';
$scope.ParentCtrl.childScope2SpecificData = '456';
}
So, you are changing ParentCtrl object in you parent scope, not for every instance.
Sorry, if it was no understandable
I try to access the value of my json objects in sap ui5, but the getproperty function cannot access the required data.
But, at first, I have created a xsodata file with some service definitions, e.g.
"CUSTOMER_ATTR_G3" as "Customers";
Then I try to get these data in view.js file with the following code:
oModel.loadData("UserInterface_G3/SERVICES/CUSTOMER_ATTR_G3.xsodata/Customers?$select=CUSTOMER_ID,CUSTOMER_DESCRIPTION&$format=json");
When I am using console.log(oModel) I see in the odata section that the values are in the object but I cannot access to them. The following screenshot should show the structure of the object:
I tried for instance:
console.log(oModel.getProperty('/CUSTOMER_DESCRIPTION'));
or
console.log(oModel.getProperty('results/CUSTOMER_DESCRIPTION'));
But I cannot access the values of the object.
Does anybody have an idea on that?
console.log(oModel.getProperty('results/CUSTOMER_DESCRIPTION'));
You need to access your Property like that:
console.log(oModel.getProperty('d/results/0/CUSTOMER_DESCRIPTION'));
You forgot the position inside of your Array. Your Path needs the position, so if you want to get the first entry CS_0001 then you have to write result/0/CUSTOMER_DESCRIPTION.
EDIT:
Actually it depends on your Model, how you have to access the Property. Can you pls show me how you defined your oModel?
I have an app with the following basic structure,
weatherDisplayController.js
weatherGrabbingService.js
userColorPreferencesService.js
When the user changes their color preferences for viewing the weather, it is stored in userColorPreferencesService.js.
However, I want to add another view where you can view all your friends' dashboards, which means creating a new micro-instance of the module. However, when I do, they will overwrite the color preferences in the Service.
How can I have multiple instances of the same module on one page?
Thats because the services are singletons. there's is only 1 existing instance of it.
Maybe make the constructor within your colorservice as a oop class and store multiple of them in the service itself.
function ColorPreferences(){
//any data
}
app.service("userColorPreferencesService", function(){
this.ownColors = new ColorPreferences({ /* data goes here */});
this.buddyColors = [];
});
//in your controller, when sharing actived
userColorPreferencesService.buddyColor = new ColorPreferences({ /* data from ajax? */});
The only varying data should be on the scope for that part of the page. Instead of storing the data in the service you could store it in each scope and pass the required data to the service.
I have a question about AngularJS behavior (JS behavior in general)
I have an Angular factory injected into a controller.
Here's a snippet of the controller code
$scope.localObjCollection= myObjFactorySvc.getObjCollection();
Let's assume that myObjFactorySvc.getObjCollection() returns the following object
[{"id":1"name":null,"address":null,"email":null},
{"id":2"name":null,"address":null,"email":null},
{"id":3"name":null,"address":null,"email":null},
{"id":4"name":null,"address":null,"email":null},
]
So, I'm pretty much using the factory to get the collection and storing it in $scope.localObjCollection.
My question is does $scope.localObjCollection have the value (copy) of the data returned by getObjCollection() or just a reference.
So if somewhere down in the controller source code, if I do
$scope.localObjCollection.push(newObj), does it also update the original collection in the Factory? It should I guess but I would like to understand the correct behavior
An array in JavaScript is an object and objects in JS are always passed/assigned by reference. Therefore your code would also update the original collection in the Factory, assuming that your myObjFactorySvc.getObjCollection() is something like this:
myObjFactorySvc.getObjCollection = function() { return someArrayVariable; }