New answer
Promises maintain their status once they have been fulfilled, this means that if you re-invoke then
on a promise that has already been fulfilled, it will invoke the callback with the result of the promise. That is to say, the promise already stores the result obtained by you !, what remains to be done is to store the promise.
The service remains like this:
app.service('svc', ['$http',
function($http) {
this.promiseCache = null;
this.getData = function(url) {
return this.promiseCache || (this.promiseCache = $http.get(url));
}
}
]);
Now the problem with this is that once Promise is resolved , you will not be able to obtain new URLs or voluntarily reload the same URL. To overcome this problem, I'll give you an example: use an arrangement for the chache by URL and with the option to download any URL.
app.service('svc', ['$http',
function($http) {
this.promiseCache = [];
this.getData = function(url, reload) {
// si se pone reload = true, se borra la cache y vuelve a empezar
if (reload) { delete this.promiseCache[url] }
// si la promise esta en la chache, retorna la promise o lanza el get
return this.promiseCache[url] || (this.promiseCache[url] = $http.get(url));
}
}
]);
Complete example: (you can check by the console that the XHR request is launched only once)
var app = angular.module('app', []);
app.service('svc', ['$http',
function($http) {
this.promiseCache = null;
this.getData = function(url) {
return this.promiseCache || (this.promiseCache = $http.get(url));
}
}
]);
app.controller('ctrl', ['$scope', 'svc',
function($scope, svc) {
$scope.reload = function() {
svc.getData('http://ipinfo.io/8.8.8.8/json')
.then(function(datos) {
$scope.datos = datos.data
});
}
// lo invocamos la primera vez.
$scope.reload();
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<pre>
{{datos | json}}
<a style="cursor: pointer" ng-click="reload()">Recargar</a>
</pre>
</div>
Original answer
Is there any way with AngularJS to keep the data even if we change our view?
Assuming that the data is in a controller (and that is why it is lost when you change your view, since it changes the controller) what you can do is use a Service.
A service
is a singleton that is born the first time it is injected and then, in subsequent injections, the same instance of the service will always be injected to all subsequent users (controllers) of the service itself.
This makes it a good tool to share information throughout the life cycle of the web app and has the advantage that with F5, when the web app is reloaded, the service is reconstructed and the data is lost.
There are many built-in services like: $interval
, $http
, $location
and others. And you can make your own.
var app = angular.module('miApp', []);
app.service('datos', ['$http', function ($http) {
// aqui dentro, this es la instancia del service.
// por lo que todo lo que almacenes aqui, sera compartido entre todos los
// contraladores que injectan el servicio.
this.unMetodo = function(url) {
return $http.get(url); // este es un ejemplo de funcion del servicio
}
}]);
Then in the controller what you must do is to inject the service (in all the contoladores)
// fijate que injectamos DATOS
app.controller('controlador1', ['$scope', 'datos', function ($scope, datos) {
// aqui dentro 'datos' es el 'this' del servicio datos.
// si haces algo como esto se refleja en todos los usuarios del servicio
datos['algo'] = 'valor';
}]);
In another controller
// fijate que injectamos DATOS
app.controller('controlador2', ['$scope', 'datos', function ($scope, datos) {
// aqui dentro 'datos' tambien es el 'this' del servicio datos.
// este controlador tiene el valor de datos['algo']
// (siempre y cuando se alla ejecutado primero el codigo del otro controller)
console.log( datos['algo'] );
}]);
Using this technique it is very easy to share resources / data between controllers and between the views.