I want to post everything that's on angular's scope service, its not much in my case but I don't want to create another object:
var model = angular.toJson($scope);
$http.post('/myUrl', model)
.success(function(data) {
});
However, it looks like $scope is a circular structure, because you can tell via: Converting circular structure to JSON when I use JSON.stringify or the string literal $Scope when I use the sample above.
Is there anyway to capture all of this data off of $scope?
This is my current hack, using underscore and underscore.string:
var toJs = function(item) {
var obj = {};
_.each(item, function(val, key) {
if (!_s.startsWith(key,'$')) {
obj[key] = val;
}
});
return obj;
};
then just passing:
toJs($scope)
You don't want to create new object, so a possible dirty solutions is to remove the circular reference and every other property you don't want to POST from $scope, call toJson, then put all previously deleted properties back to $scope.
Nest a child property on $scope and call toJson on that.
<input ng-model='email'>
becomes
<input ng-model='user.email'>
so that
$http.post('/url', angular.toJson($scope.user));
Related
I am trying to pass object, controller to another controller using '$sessionStorage'
My first controller, I set the object to the session.
$scope.expandChart = function(obj){
$sessionStorage.chartObject = obj;
$state.go('app.chart-full-view');
}
after i am trying to access this object in another controller. please check below code
Second controller (this is 'chart-full-view' controller)
$scope.test = $sessionStorage.chartObject;
console($scope.test);
when I console my object, console log printed correctly with error. What is this error? I need to correctly access this.
as a solution i tried below way. but did not working
$scope.test = JSON.stringify($sessionStorage.chartObject);
Error is "angular.js:15697 TypeError: Converting circular structure to JSON "
You should use stringify when saving the object in sessionStorage and then use parse when getting it
sessionStorage.setItem("chartObject", JSON.stringify(obj));
As you cannot save objects in sessionstorage only strings.
And then
$scope.test = = JSON.parse(sessionStorage.getItem('chartObject'));
I have a web service that returns an object called response. It has an object data. When I do the following:
var myObject = JSON.stringify(response.data);
console.log("My Results: " + myObject);
[{"id":"1","username":"sam","user_id":"1","status":"1"}]
But I am having trouble accessing these objects in a scope.
for example
$scope.myresponse = response.data;
$scope.myresponse.username = response.data.username
It doesn't work. I even tried $scope.myresponse = response.data[0]; that didnt' work either. Any suggestions?
Store response return from backend call inside a service layer variable and access that variable from controller to get the required result.
Demo code showing above interaction...
In ServiceLayer.js
var myObject = response["data"];
function getMyObject() {
return myObject;
}
In Controller.js
Inject that registered service and access myObject variable.
$scope.myresponse = this.serviceLayer.getMyObject();
use this myResponse variable to access any required information.
Regards
Ajay
Actually the solution turned out be an easy one. Not very clean but it works.
$scope.myData = response.data;
$scope.myResults = $scope.myData[0];
After this I was able to access all the elements e.g. id by {{myResults.id}} in my view.
Thank you all for your help.
I have the following controller in Angular that reads some records from DB and then outputs them into a calendar. The problem is that the events array comes back as empty. I have tried using $rootScope.events as a substitute, but that gives an error "concat is not a function of undefined." What am I doing wrong? Is there some trickery with nested scopes?
I also just realized that eachActivity variable is undefined in the inner callback, as well. I assume this is a part of a general knowledge I am lacking.
app.controller('Calendar', ['$scope','$rootScope','$resource','moment', function($scope, $rootScope, $resource ,moment) {
var Activities = $resource('/api/activities');
Activities.query(function(activities){
$rootScope.activities = activities;
//console.log($rootScope.activities);
});
//console.log($rootScope.activities);
var vm = this;
var events = [];
//define the calendar on rootScope, so it has access to the Events data from the other controllers
$rootScope.calendar = new moment();
angular.forEach($rootScope.activities, function(eachActivity){
//console.log(eachActivity.events);
if (eachActivity.events.length > 0){
angular.forEach(eachActivity.events, function(eachEvent, eachActivity){
console.log(eachEvent);
var entry = {
title: eachActivity.title,
type: "warning",
startsAt: eachEvent.startDate,
endsAt: eachEvent.endDate,
incrementBadgeTotal: true
}
events.concat(entry);
});
}
});
vm.events = events;
console.log(vm.events);
vm.calendarView = 'month';
vm.viewDate = moment().startOf('month').toDate();
vm.isCellOpen = true;
}]);
To solve your immediate problem, change
angular.forEach(eachActivity.events, function(eachEvent, eachActivity)
to
angular.forEach(eachActivity.events, function(eachEvent)
The second argument is not necessary as eachActivity has already been defined in the outer loop.
Also change events.concat(entry); to events.push(entry);
In addition, instead of defining calendar on $rootScope, create a calendar factory instead and inject that into the controllers where you need to access calendar data. There are a number of reasons why this is better but the simplest is that $scopes are not meant for sharing data between controllers. They are primarily meant to act as a view model to bind data between your views and controllers.
EDIT (more details on creating a factory)
You can define a factory like so
app.factory('CalendarService', [function(){
var calendarEvents = []; // or {} or even null depending on how you want to use the variable
return {
calendarEvents : calendarEvents
};
}]);
In your controller,
app.controller('Calendar', ['$scope','$rootScope','$resource','moment', 'CalendarService', function($scope, $rootScope, $resource ,moment, CalendarService) {
...
// instead of $rootScope.calendar = new moment (and I don't understand why you are assigning this to a moment but that's another conversation
CalendarService.calendarEvents = events;
}]);
All you need to do is inject CalendarService into every controller where you need to use the events data and it will be available in the calendarEvents field.
There are a few things going on here:
1) The concat() method returns a new array comprised of the array on which it is called joined with the array(s) and/or value(s) provided as arguments. You'll need to assign the vaues: events = events.concat(entry) for them to persist for the next iteration.
2) You have nested Angular Loops. Often necessary, but be careful with your naming conventions.
angular.forEach($rootScope.activities, function(eachActivity){
angular.forEach(eachActivity.events, function(eachEvent, eachActivity)
Here your loops share identical argument names. This is highly discouraged because it can really create headaches for the developer trying to understand the scope of the object being iterated over. I'd suggest ensuring that your names are always unique and explicit to the scope.
3) Because you are overriding your argument names, your call to title: eachActivity.title is going to be looking at the inner loops second argument, which in this case is the KEY of the event within the forEach loop eachActivity.events object. Keys do not have properties, they are always strings - because of this your eachActivity variable is defined, yet it has no properties.
I'd suggest altering these few things and then editing your post with any progress made.
I'm having a problem where the cached object doesn't resemble the correct data so I figured it I can push up the most uptodate version to the browser cache it will solve my problem.
How do you update your localStorage with a new object? So if I had a controller with that had an assessment updated. How can I push that assessment object up to the localStorage?
To do that with native JavaScript, you would do something like this:
localStorage.setItem('itemKey', JSON.stringify(yourObject));
var item = JSON.parse(localStorage.getItem('itemKey'));
Within the context of angular, you should make a localStorage service as a wrapper around localStorage and inject it into your service or controller. Or you could inject $window and use it directly off of that like: $window.localStorage
A response specifically for the asker of this duplicate question:
LocalStorage can only store strings, which is why you're stringifying your object before storing it. To manipulate the stored string as an object, you can pass it to JSON.parse (assuming it's properly JSON-formatted). Then to store the modified version, you need to convert it back into a string.
// Creates JSON-formatted object, converts it to a string and stores the string as "ship"
const ship = { name: "black pearl", captain: "Jack Sparrow" };
const originalStringifiedForStorgage = JSON.stringify(ship);
localStorage.setItem("ship", JSON.stringify(ship));
// Retrieves the string and converts it to a JavaScript object
const retrievedString = localStorage.getItem("ship");
const parsedObject = JSON.parse(retrievedString);
// Modifies the object, converts it to a string and replaces the existing `ship` in LocalStorage
parsedObject.name = "newName";
const modifiedndstrigifiedForStorage = JSON.stringify(parsedObject);
localStorage.setItem("ship", strigifiedForStorage);
If the object is in JSON format (not sure if Angular uses a different format) you could probably use the setItem() and getItem() methods to update and retrieve local storage items!
For example taken from the following post:
http://thejackalofjavascript.com/storing-objects-html5-local-storage/
var me = {name:'myname',age:99,gender:'myGender'};
localStorage.setItem("user",me);
//fetch object
console.log(localStorage.getItem("user")); // will return "[object Object]"
You can use full featured Angular module angular-local-storage
An AngularJS module that gives you access to the browsers local
storage with cookie fallback
set
myApp.controller('MainCtrl', function($scope, localStorageService) {
//...
function submit(key, val) {
return localStorageService.set(key, val);
}
//...
});
get
myApp.controller('MainCtrl', function($scope, localStorageService) {
//...
function getItem(key) {
return localStorageService.get(key);
}
//...
});
setItem wont work instead it will create another item in localStorage with the same name
Instead directly use
localStorage.item = (what ever the change that you want in the item)
I use angular.copy in some cases, like copying model default values to the form model, like this:
var customerModel = {
name: '',
point: 0
};
$scope.customer = angular.copy(customerModel);
function save() {
//... Reset $scope.customer after success submit
$scope.customer = angular.copy(customerModel);
}
... to prevent the default customerModel changed.
But why copy empty object or array? {} or []
I found in some codes used angular.copy on empty object or array. Why they don't assign empty object directly to the variable?
$scope.customer = {}; // or [] for array
If you use copy on empty object or array, could you explain the benefit?
What about ajax response ($http)?
And one more question, what did you do to ajax response? copy or assign it directly to a variable?
$http
.get('example.com/api/v1/get/customer/1')
.success(function(response) {
$scope.customer = angular.copy(response.data);
// or do you use $scope.customer = response.data ?
})
;
And if you used copy, what do you think happened to the response object?
Is it remain in the memory? or deleted automatically?
You copy an object to prevent other code from modifying it. (original object might change, but your copy won't see the changes)
If you were to do this:
$scope.customer = customerModel
... and some callback/service/whatnot changed customerModel, your scope would reflect this change. This is not always desirable, hence the need for deep copying.
Copying empty literal object
$scope.customer = angular.copy({})
// or
$scope.customer = {}
This doesn't make any difference. It's a new empty object every time. Note that it's very different from this:
this.customerModel = {};
$scope.customer = angular.copy(this.customerModel)
Copying ajax response data
Same rules apply. If you want to ensure that this object doesn't change from underneath you (which may happen if you also passed it to somewhere else, for example), you should copy it.
angular.copy creates deep copy of variable so that it would hold the reference of another variable
sometimes it happens when user dont want to use call by reference then deep copy comes in action According to your question
var customerModel = {
name: '',
point: 0
};
If you will use $scope.customer = angular.copy(customerModel); it will create deep copy of customerModel
As far as $http Service is concerned .Data is coming from response and If you you will assign It directly then there would be no effect of call by reference because data is coming from another source.
So I would rather assign it directly in case of $http.get()