I am new to angular and I want to pass data from one page to another page using local storage.I have tried a lot but unable to find the correct answer
Use factory like below.
angular
.module('xx.services', [])
.factory('xxStorage', ['$window', function($window) {
return {
set: function(_key, _value) {
$window.localStorage[_key] = _value;
},
get: function(_key) {
return $window.localStorage[_key];
}
};
}])
You can use set function to save data in the first page, and then reuse using get function in the other page.
The best way is to use library which already wrapped localStorage functionality in angular area. So there are few such popular solutions like: ngStorage and angular-local-storage. I prefer first one.
Git page, here you can find all information about installing, and using.
Just for example here is sample
var app = angular.module('app', ['ngStorage'])
.config(['$localStorageProvider',
function ($localStorageProvider) {
$localStorageProvider.get('MyKey');
$localStorageProvider.set('MyKey', { k: 'value' });
}]);
Related
I am new to Angular js and want to set the global variable that I can use it on different different services as webservice url.
I have implemented app.js (module) like this:
var app;
(function () {
app = angular.module("ANG", []);
app.value('user', {
urlBase: ''
});
})();
When I want to use this constants values I just define it in the service defination and use it but I want to store the details in that so no need to set values again and again.
Example:
When I login in the system I return some data with webserviceurl with it and I set that url in the value.urlBase in login controller.
But when I go to different service and want to use that it sets the values back to ''.
CODE to use constant values:
app.service('servicename', ["$http", "$q", 'user', function ($http, $q, user) {
//access the user here but it gives value ''.
console.log(user.urlBase);
}
How can I store at once and use it again and again?
You can actually use a 'constants' file, like so:
export default angular
.module('my.module', [])
.constant('someConstant', Object.freeze({
foo: 1,
bar: 2
})
.name;
We use Object.freeze() in ours, but you can use immutable.js or something like that to prevent mutation.
I suggest you have another service, rather than a value.
Pass a userService to your services, that contains the user object that is either accessible as a property, or retrieved via a getter:
app.factory('userService', function() {
var user = {
urlBase: ''
};
return {
user: user
};
};
app.service('servicename', ['userService', function (userService) {
console.log(userService.user.urlBase);
}]);
Then where you set the urlBase, you are also passing the userService. Services are generally singletons, so it should preserve the user between other services.
UPDATE:
As you need to preserve the details between page refreshes, a cookie is not a bad solution. In your loginService, you set the cookie value, and in your other services, read from the cookie. This is done using the $cookies service in Angular (https://docs.angularjs.org/api/ngCookies/service/$cookies)
app.service('loginService', ['$cookie', function ($cookies) {
$cookies.put('userUrl', 'http://urlhere');
}]);
app.service('servicename', ['$cookie', function ($cookies) {
console.log($cookies.get('userUrl'));
}]);
Another option is to use local storage, and this SO has an example of doing so and preserving state:
How do I store data in local storage using Angularjs?
You can use constant files like this.
app = angular.module("ANG", []);
app.constant('user', {
urlBase: {
'url':'what ever the URL is'
}
});
I'd like to know how what is the best (and most secure) way to pass parameters (such as product id) between views so the user cannot see them in the url bar.
Thank you.
Stephan
You should pass them from one controller to another controller in the new view. Here is a pretty good answer on how to do that: LINK
Store them in a shared service and use them when you need them, quick sample:
app.factory("shared", function() {
var data = null;
return {
setData: function(someData) {
data = someData;
},
getData: function() {
return data;
}
}
});
And now use it!
app.controller("myCtrl", function($scope, shared) {
$scope.data = shared.getData();
});
A good way to do this is to use the Angular Service pattern.
Because the controllers are functions and the services are objects (singletons) You can have multiples services according to the differents functionnalities that you have in your app.
You should see the documentation for Angular providers here :
https://docs.angularjs.org/guide/providers
The best way of handling Firebase in AngularJS surely has to be from within a service, so it's available to all Controllers across the App.
I just can't get it to work! ... I first tried using angularFire(new Firebase(url)), hoping I could bind to the service's scope, but Angular complains that it cannot $watch it.
So I tried angularFireCollection instead like this:
app.factory('myService', function myService(angularFireCollection) {
var url = 'https://myfirebase.firebaseio.com';
return {
getAll: function(path) {
var ref = angularFireCollection(new Firebase(url + '/' + path));
console.log(ref);
return ref;
},
...
};
});
However, the angularFireCollection is an Object containing a load of methods etc. if I bind it to a controller $scope I just get garbage. It also complains that it can't call the Firebase functions before I try to use them (e.g. Error: Firebase.push failed: second argument must be a valid function.)... anyone got any ideas where I'm going wrong?
See this PLUNKER
If you want to encapsulate some of the functionality into a service, consider keeping the returned ref in state of the service. I expanded on your plunker. It seems to mostly do what you were trying for.
http://plnkr.co/edit/Uf2fB0
Jeff answered the question correctly ... I'm just posting a further development on Jeff's example for those who are interested.
I have abstracted the Firebase service creation, so you can dynamically create an instance of whatever Firebase service you want:-
var registerFirebaseService = function (serviceName) {
app.factory(serviceName, function (angularFire) {
var _url = null;
var _ref = null;
return {
init: function (url) {
_url = url;
_ref = new Firebase(_url);
},
setToScope: function (scope, localScopeVarName) {
angularFire(_ref, scope, localScopeVarName);
}
};
});
};
You first create an instance of the service as follows
registerFirebaseService('itemsService'); // create itemsService instance
Then you can inject the itemsService service into your controllers. The instance is initialised using your Firebase URL e.g.
itemsService.init('https://firebase.firebaseio.com/' + userId + '/items');
The Firebase can now be bound to your controller e.g.
itemsService.setToScope($scope, 'items');
adapted PLUNKER
In an angularjs app, I am attempting to use a custom service to hold the app's main data, "items". However, I would like to bootstrap the data into the service upon the initial page load, in order to avoid a separate ajax request to the server to get it. What would be cleanest way to go about doing this?
Here is a snippet of my service for reference:
app.factory('items', function() {
var itemsService = {},
items = [];
itemsService.list = function() {
return items;
};
itemsService.add = function() {
/* ... */
};
return itemsService;
});
And on the backend I am using node.js + expressjs + jade, so I would be injecting the data into the page using:
!{JSON.stringify(items)}
Put your bootstrapped data from the server into a global JavaScript variable. Have your service assign items to that global variable (or copy the data into items).
How about something like this:
app.run(['items', function (items) {
items.load();
}])
This presumes your items service has a load function (or something like it) that does the actual Ajax work using either $http or $resource.
Currently I have an Angular.js page that allows searching and displays results. User clicks on a search result, then clicks back button. I want the search results to be displayed again but I can't work out how to trigger the search to execute. Here's the detail:
My Angular.js page is a search page, with a search field and a search
button. The user can manually type in a query and press a button and
and ajax query is fired and the results are displayed. I update the URL with the search term. That all works fine.
User clicks on a result of the search and is taken to a different page - that works fine too.
User clicks back button, and goes back to my angular search page, and the correct URL is displayed, including the search term. All works fine.
I have bound the search field value to the search term in the URL, so it contains the expected search term. All works fine.
How do I get the search function to execute again without the user having to press the "search button"? If it was jquery then I would execute a function in the documentready function. I can't see the Angular.js equivalent.
On the one hand as #Mark-Rajcok said you can just get away with private inner function:
// at the bottom of your controller
var init = function () {
// check if there is query in url
// and fire search in case its value is not empty
};
// and fire it after definition
init();
Also you can take a look at ng-init directive. Implementation will be much like:
// register controller in html
<div data-ng-controller="myCtrl" data-ng-init="init()"></div>
// in controller
$scope.init = function () {
// check if there is query in url
// and fire search in case its value is not empty
};
But take care about it as angular documentation implies (since v1.2) to NOT use ng-init for that. However imo it depends on architecture of your app.
I used ng-init when I wanted to pass a value from back-end into angular app:
<div data-ng-controller="myCtrl" data-ng-init="init('%some_backend_value%')"></div>
Try this?
$scope.$on('$viewContentLoaded', function() {
//call it here
});
I could never get $viewContentLoaded to work for me, and ng-init should really only be used in an ng-repeat (according to the documentation), and also calling a function directly in a controller can cause errors if the code relies on an element that hasn't been defined yet.
This is what I do and it works for me:
$scope.$on('$routeChangeSuccess', function () {
// do something
});
Unless you're using ui-router. Then it's:
$scope.$on('$stateChangeSuccess', function () {
// do something
});
angular.element(document).ready(function () {
// your code here
});
Dimitri's/Mark's solution didn't work for me but using the $timeout function seems to work well to ensure your code only runs after the markup is rendered.
# Your controller, including $timeout
var $scope.init = function(){
//your code
}
$timeout($scope.init)
Hope it helps.
You can do this if you want to watch the viewContentLoaded DOM object to change and then do something. using $scope.$on works too but differently especially when you have one page mode on your routing.
$scope.$watch('$viewContentLoaded', function(){
// do something
});
You can use angular's $window object:
$window.onload = function(e) {
//your magic here
}
Another alternative:
var myInit = function () {
//...
};
angular.element(document).ready(myInit);
(via https://stackoverflow.com/a/30258904/148412)
Yet another alternative if you have a controller just specific to that page:
(function(){
//code to run
}());
When using $routeProvider you can resolve on .state and bootstrap your service. This is to say, you are going to load Controller and View, only after resolve your Service:
ui-routes
.state('nn', {
url: "/nn",
templateUrl: "views/home/n.html",
controller: 'nnCtrl',
resolve: {
initialised: function (ourBootstrapService, $q) {
var deferred = $q.defer();
ourBootstrapService.init().then(function(initialised) {
deferred.resolve(initialised);
});
return deferred.promise;
}
}
})
Service
function ourBootstrapService() {
function init(){
// this is what we need
}
}
Found Dmitry Evseev answer quite useful.
Case 1 : Using angularJs alone:
To execute a method on page load, you can use ng-init in the view and declare init method in controller, having said that use of heavier function is not recommended, as per the angular Docs on ng-init:
This directive can be abused to add unnecessary amounts of logic into your templates. There are only a few appropriate uses of ngInit, such as for aliasing special properties of ngRepeat, as seen in the demo below; and for injecting data via server side scripting. Besides these few cases, you should use controllers rather than ngInit to initialize values on a scope.
HTML:
<div ng-controller="searchController()">
<!-- renaming view code here, including the search box and the buttons -->
</div>
Controller:
app.controller('SearchCtrl', function(){
var doSearch = function(keyword){
//Search code here
}
doSearch($routeParams.searchKeyword);
})
Warning : Do not use this controller for another view meant for a different intention as it will cause the search method be executed there too.
Case 2 : Using Ionic:
The above code will work, just make sure the view cache is disabled in the route.js as:
route.js
.state('app', {
url : '/search',
cache : false, //disable caching of the view here
templateUrl : 'templates/search.html' ,
controller : 'SearchCtrl'
})
Hope this helps
I had the same problem and only this solution worked for me (it runs a function after a complete DOM has been loaded). I use this for scroll to anchor after page has been loaded:
angular.element(window.document.body).ready(function () {
// Your function that runs after all DOM is loaded
});
You can save the search results in a common service which can use from anywhere and doesn't clear when navigate to another page, and then you can set the search results with the saved data for the click of back button
function search(searchTerm) {
// retrieve the data here;
RetrievedData = CallService();
CommonFunctionalityService.saveSerachResults(RetrievedData);
}
For your backbutton
function Backbutton() {
RetrievedData = CommonFunctionalityService.retrieveResults();
}
call initial methods inside self initialize function.
(function initController() {
// do your initialize here
})();