Hi I am developing my first Angularjs application. I want to save data in Angularjs application for later use(I have used localstorage in jquery before).
For example, I will make ajax call and i will get some data, Lets say below example,
$http.post('http://192.168.0.213:1234/api/VerifyUser', $stateParams.pageList).then(function (response) {
alert(response.data);
another example, After succesfull login i will get some ID in response and i want to preserve this data all over the application. This ID i may use in all subsequent ajax calls.
I will get some data in response and i want to make use that data in other controllers as well. Is there any way i can do this? any help would be appreciated. Thank you.
you can store it in factory like below,
After your Ajax call
$http.post('http://192.168.0.213:1234/api/VerifyUser', $stateParams.pageList).then(function (response) {
alert(response.data)
SomeFactory.setData(response.data);
};
SomeFactory
(function () {
'use strict';
angular
.module('app.myApp')
.factory('SomeFactory', SomeFactory);
SomeFactory.$inject = [];
function SomeFactory() {
var someData;
var factory = {
setData: setData,
getData: getData
};
function setData(data) {
someData = data;
}
function getData() {
return someData;
}
return factory;
}
})();
In your Controllers
inject your factory to your controller and then getdata
(function () {
'use strict';
angular
.module('app.login')
.controller('LoginController', LoginController);
LoginController.$inject = ['SomeFactory'];
function LoginController(SomeFactory) {
var vm = this;
vm.someVariable = SomeFactory.getData();
console.log(vm.someVariable); // logs your data
}
})();
Sharing data between controllers can be achieved with the following options :
Factory
Service
Then you can inject the service across the controllers and use the data whenever you need.
app.service('myService', function($http) {
this.getJSON = function() {
$http.post('http://192.168.0.213:1234/api/VerifyUser', $stateParams.pageList).then(function(response) {
return response.data;
});
};
});
In Controller:
app.controller('myController', function($scope, myService) {
myService.getJSON().then(function(data) {
$scope.myData = data;
console.log(data);
});
});
DEMO
Use Service to store the data and get the data in another controller later on.
When you inject a Service, it's the same service in every controller - so you can access the properties and methods in that service all over.
https://docs.angularjs.org/guide/services
Example:
.service('YourService', function(){
var YourService = {};
YourService.yourvar = '';
return YourService;
})
.controller('controller1', function($scope, YourService){
YourService.yourvar = 'blah';
})
.controller('controller2', function($scope, YourService){
$scope.currentYourVar = YourService.yourvar;
})
Related
This is more of a writing clean code/ optimizing existing code.
I am writing my Angular Services to fetch data from backend like this
angular.module('myApp').service('Auth', ['$http', '$q', 'Config', function($http, $q, Config) {
this.getUser = function() {
return $http.get(Config.apiurl + '/auth/user')
.then(function(response) {
return response.data;
}, function(error) {
return $q.reject(error.data);
});
};
}]);
Now in this, I am calling getUser function n number of times from the Database.
Now the question is, is it okay to call this service to get n times redundant data or I should it be saved somewhere say rootscope to be accessed later? Or storing in root scope would be bad practice and I should consider some other option or nothing at all?
Would like to get some views on Angular Community here.
Here is a sample example on how to use factory for sharing data across the application.
Lets create a factory which can be used in entire application across all controllers to store data and access them.
Advantages with factory is you can create objects in it and intialise them any where in the controllers or we can set the defult values by intialising them in the factory itself.
Factory
app.factory('SharedData',['$http','$rootScope',function($http,$rootScope){
var SharedData = {}; // create factory object...
SharedData.appName ='My App';
return SharedData;
}]);
Service
app.service('Auth', ['$http', '$q', 'SharedData', function($http, $q,SharedData) {
this.getUser = function() {
return $http.get('user.json')
.then(function(response) {
this.user = response.data;
SharedData.userData = this.user; // inject in the service and create a object in factory ob ject to store user data..
return response.data;
}, function(error) {
return $q.reject(error.data);
});
};
}]);
Controller
var app = angular.module("app", []);
app.controller("testController", ["$scope",'SharedData','Auth',
function($scope,SharedData,Auth) {
$scope.user ={};
// do a service call via service and check the shared data which is factory object ...
var user = Auth.getUser().then(function(res){
console.log(SharedData);
$scope.user = SharedData.userData;// assigning to scope.
});
}]);
In HTML
<body ng-app='app'>
<div class="media-list" ng-controller="testController">
<pre> {{user | json}}</pre>
</div>
</body>
Instead of rootScope just use a local variable of user in your service that can be accessed from anywhere in your code and so you doesn't have to call the api every time.
angular.module('metaiotAdmin').service('Auth', ['$http', '$q', 'Config', function($http, $q, Config) {
this.getUser = function() {
if(this.user){
return this.user;
}
else{
return $http.get(Config.apiurl + '/auth/user')
.then(function(response) {
this.user = response.data;
return response.data;
}, function(error) {
return $q.reject(error.data);
});
}
};
}]);
Hope it helps.
You don't have to, $http already caches your request for you, if the same request is applied in case you set the cache config option to true.
$http.get('/hello', { cache: true})
.then(onResponse)
or you can either set it for every request, by using either an interceptor or override the http instance in the $httpProvider, to apply the effect for every http request.
app.module('app.module')
factory('MyHttpInterceptor', function() {
return {
request : function(config) {
config.cache = true;
return config;
},
// rest of implementation of the interceptor
}
});
app.module('app.module')
.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('MyHttpInterceptor');
// ... rest of the configuration
}]);
Or :
app.module('app.module')
.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.cache = true;
// ...
}]);
see :
Angular doc for caching
I'm newer in AngularJS. So I have a simple question, but I can't find answer. I have code:
angular.module('app', ['app.controllers', 'ngRoute']).
config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/users', {templateUrl: '../pages/list.html', controller: 'UserListCtrl'}).
when('/user-details/:login', {templateUrl: '../pages/form.html', controller: 'UserCtrl' /* and here I need to call userDetails(login) from UserCtrl */}).
otherwise({redirectTo: '/users'});;
}
]);
app.controller('UserCtrl', function ($scope, $http, $location) {
$scope.userDetails = function (login) {
$http.get(url + login).success(function (data) {
$scope.user = data[0];
console.log('tst');
}).error(errorCallback);
};
$scope.createUser = function (user) {
$http.post(url, user).success(function (data) {
$location.path('/users');
}).error(errorCallback);
};
});
My problem is: I don't know how to call specific method of controller when routing matches. I need to call method and give to it parameter :login from routing. How to solve this?
Thanks for your answers
If I understand correctly, you are re-using the same controller for two parts of the view (or for two views), one for creating a user and one for fetching the details of the current user.
Since these two aspects are totally different, it is not advisable to use the same controller for both. The controllers should be different and any common or re-usable functionality should be shared through a service.
In any case, code that makes calls to the backend should not be placed inside controllers, but into services. E.g.:
app.service('UserSrv', function ($http) {
var url = '...';
this.userDetails = function (login) {
return $http.get(url + login);
};
this.createUser = function (user) {
return $http.post(url, user);
};
});
app.controller('UserCtrl', function ($scope, UserSrv) {
var login = '...';
var errorCallback = ...;
// Fetch user details upon initialiation
UserSrv.userDetails(login).success(function (data) {
$scope.user = data[0];
}).error(errorCallback);
});
app.controller('NewUserCtrl', function ($location, $scope, UserSrv) {
var errorCallback = ...;
$scope.createUser = function (user) {
UserSrv.createUser(user).success(function (data) {
$location.path('/users');
}).error(errorCallback);
};
});
You could, also, use $routeProvider's resolve property to "preload" the user's details and pass it to the UserCtrl as an argument.
I am trying to create factory for the restful services.
I need to make service calls. First call's data will be used to get the second calls data.
My problem is I don't know how to transfer data from one controller to another controller.
Is there a better way to do my codes?
Here are my codes...
var app = angular.module('myApp', []);
//getting init data via service
app.factory('myService', function($http) {
var myService = {
async: function() {
var promise = $http.get('test/test.json').then(function (response) {
return response.data;
});
return promise;
}
};
return myService;
});
//retrieve data
app.controller('testCtrl', function(myService, $scope, $http) {
myService.async().then(function(data) {
$scope.data = data
//using retrieve data to get another piece of data
vay first = data[0].employee[0];
})
$http({
url: "test?" + first +'.json',
method: "GET",
}).success(function(secondData) {
$scope.secondData=secondData //How do I pass data to my secondCtrl?
})
})
app.controller('secondCtrl', function($scope) {
// I need to be able to get the secondData from testCtrl.
console.log($scope.secondData)
})
Thanks for the help!
Why don't you store the data as an object in the service itself, then both controllers depend on the service and have access to the data. Like this:
app.factory('myService', function($http) {
var that = this;
var myService = function($http) {
this.set = function(url) {
var promise = $http.get(url).then(function (response) {
that.data = promise.data;
});
return promise;
}
};
return new myService($http);
});
Then your controller sets and gets the data in the way
app.controller('testCtrl', function(myService, $scope, $http) {
myService.set('someurl').then(function() {
$scope.data = myservice.data;
//using retrieve data to get another piece of data
vay first = data[0].employee[0];
myservice.set('someOtherUrl?data='+first);
})
app.controller('secondCtrl', function($scope, myservice) {
//the data object on the myservice function has been changed on the first controller and we can reasonably expect the data we need. If these 2 controllers coexist in the same space and time we can wrap this in a $watch service
console.log(myservice.data)
});
$watch service example
app.controller('secondCtrl', function($scope, $watch, myservice) {
$watch('myservice.data', function(newval, oldval) {
console.log(newval);
}, true)
//I will only log the newvalue of myservice.data when the data has changed. the last true argument is a neccesity so that angular will compare the values within the object
});
You could either extend 'myService' to contain the response data, using it in both controllers, or you could create another service for sharing data between them.
Both solutions would look similar, but here is what the second option (new service) might look like:
Factory
.factory('SharedService', function(){
var shared = {
data: ''
}
return shared;
})
This factory could act as just a place to store some data. In fact, if all you'd like to do is share data, you could just use a value provider. But a factory you could later extend with a more complex data structure and methods.
In your controllers, just inject the service and, optionally, set it to a scope variable:
Controller 1
.controller('FirstController', function($scope, SharedService){
$scope.shared = SharedService;
$scope.shared.data = 'foo';
})
$scope.shared now references the service object. If you were to do the same in the other controller, they could both read/write to that same object:
Controller 2
.controller('SecondController', function($scope, SharedService){
$scope.shared = SharedService;
console.log($scope.shared.data); // 'foo' if called after first ctrl set it
})
Demo
I am currently working myself through tutorials and books teaching AngularJS.
I want to write a simple app, that loads some user data from a json file and displays it.
Now this is the relevant part of a JavaScript file, which does what I want:
Here is my Code :
angular.module('myModule', [])
.controller('myCtrl', function($scope, $http) {
$http.get('../mockdata/users_js.json').success(function(data, status, headers, config) {
$scope.users = data;
});
});
Now if I try to create a separate module for importing my data, I fail:
angular.module('myModule', [])
.controller('myCtrl', function($scope, Users) {
$scope.users = Users.query();
})
.factory('Users', function($http) {
var users = {};
users.query = function() {
// In real apps, we'd pull this data from the server...
$http.get('../mockdata/users_js.json').success(function(data, status, headers, config) {
this.data = data;
});
return this.data;
};
return users;
});
What am I doing wrong ?
And How can i fix this ?
In users.query() you kick off an asynchronous HTTP request, and then before it has a chance to finish return this.data which is undefined.
You could take a look at $resource, it returns a promise that you can assign to a $scope variable immediately. It will apply the right value when the request completes.
.factory('Users', function($resource) {
var users = {};
users.query = function() {
return $resource('../mockdata/users_js.json').get();
};
return users;
});
If you want to know how to do this with $http:
angular.module('myModule', [])
.controller('myCtrl', function($scope, Users) {
Users.then(function(data){
$scope.users = data;
});
})
.factory('Users', function($http) {
var Users = {};
Users = $http.get('../mockdata/users_js.json').then(function (response) {
return response.data;
});
return Users;
});
Here's a live Plnkr.
How can I use angular-resources.js to read in a JSON file through a service?
I am working on a very basic Angular app for testing purposes and am just trying to read in data from JSON file right now. I am placing this code in a service so I can more easily swap it out when we move a server based data store.
My App and App.controller declaration are as follows:
'use strict';
// create module for custom directives
var App = angular.module('App', ['jsonService']);
// controller business logic
App.controller('AppCtrl', function AppCtrl($scope, JsonService) {
console.log("marker 1");
if (!$scope.jsonData) {
console.log("marker 2");
JsonService.getData(function (d) {
console.log(d);
$scope.jsonData = d;
$scope.records = d.length;
});
} else {
console.log("I have data already... " + $scope.jsonData);
}
console.log($scope.jsonData);
});
My JsonService is defined as the follow, at the moment:
'use strict';
angular.module('jsonService', ['ngResource'])
.factory('JsonService', function($resource, $filter) {
// define the remote service using Angular's $resource module
var service = $resource('/data/ProcessModeling-Resources.json', {});
var JsonService = {
// calls $resource.query() to retrieve the remote data.
getData : function getData(callback) {
console.log("marker 3");
service.query(function (data) {
console.log("marker 4");
});
}
};
return JsonService;
});
The console output I am getting follows:
marker 1 app.js:8
marker 2 app.js:11
marker 3 services.js:13
undefined app.js:21
TypeError: Object #<Resource> has no method 'push'
at copy (http://127.0.0.1:8000/lib/angular.js:556:21)
at new Resource (http://127.0.0.1:8000/lib/angular-resource.js:330:9)
at http://127.0.0.1:8000/lib/angular-resource.js:386:32
at forEach (http://127.0.0.1:8000/lib/angular.js:117:20)
at http://127.0.0.1:8000/lib/angular-resource.js:385:19
at wrappedCallback (http://127.0.0.1:8000/lib/angular.js:6650:59)
at http://127.0.0.1:8000/lib/angular.js:6687:26
at Object.Scope.$eval (http://127.0.0.1:8000/lib/angular.js:7840:28)
at Object.Scope.$digest (http://127.0.0.1:8000/lib/angular.js:7707:25)
at Object.Scope.$apply (http://127.0.0.1:8000/lib/angular.js:7926:24) angular.js:5582
I'm receiving my error when I attempt to call my service.query(function (data) { }, which (if I'm understanding correctly) should be pulling my JSON file in.
I've been using AngularJS Cats App as an example for pulling data.
I'd follow #pkozlowski's advice and make sure the response is an array. Anyway, here's an example that loads data from a JSON file similar to what you describe in your comments. It uses ngResource and can help you put things together: http://plnkr.co/edit/Ofq7Md8udEnIhAPF1NgL?p=preview
The service
angular.module('jsonService', ['ngResource'])
.factory('JsonService', function($resource) {
return $resource('cats.json',{ }, {
getData: {method:'GET', isArray: false}
});
});
Notice that isArray is set to false.
Your app and controller
var app = angular.module('app', ['jsonService']);
app.controller('ctrl', function($scope, JsonService){
JsonService.getData(function(data){
$scope.name = data.name;
$scope.children = data.children;
});
});
getData is actually not needed since the Resource class gives you some useful convenience methods such a get, you can just do this
angular.module('jsonService', ['ngResource'])
.factory('JsonService', function($resource) {
return $resource('cats.json');
});
app.controller('ctrl', function($scope, JsonService){
JsonService.get(function(data){
$scope.name = data.name;
$scope.children = data.children;
});
});