I can't figure out how to destroy my cache to get a new list from my server.
When I get the first list, it's work perfect, but after inserting informations to my database and sending another get to my server, the browser only show the cached version of my list, without the new data.
I tried to use cacheFactory like this:
$cacheFactory.get('$http').removeAll();
but it doesn't worked.
Here is my angular Module, Service and Controller.
Module myApp
var app = angular.module('myApp', ['ngRoute', 'LocalStorageModule', 'angular-loading-bar', 'smart-table']);
app.config(function ($routeProvider) {
$routeProvider.when("/home", {
controller: "homeController",
templateUrl: "/web/views/home.html"
});
$routeProvider.when("/cidades", {
controller: "cidadesController",
templateUrl: "/web/views/basico/cidades/cidades.html"
});
$routeProvider.otherwise({ redirectTo: "/home" });
});
app.config(function ($httpProvider) {
$httpProvider.interceptors.push('authInterceptorService');
});
app.run(['authService', function (authService) {
authService.fillAuthData();
}]);
cidadesService
'use strict';
app.factory('cidadesService', ['$http', '$cacheFactory', function ($http, $cacheFactory) {
var serviceBase = 'http://localhost:22207/';
var serviceFactory = {};
var _getCidades = function () {
$cacheFactory.get('$http').removeAll(); //This doesn't worked
return $http.get(serviceBase + 'api/cidades/getall').then(function (results) {
return results;
});
};
serviceFactory.getCidades = _getCidades;
return serviceFactory;
}]);
cidadesController
'use strict';
app.controller('cidadesController', ['$scope', 'cidadesService', function ($scope, service) {
$scope.cidade = {
id: "",
nome:"",
};
$scope.message = "";
$scope.getCidades = function () {
service.getCidades().then(function (results) {
$scope.cidades = [];
$scope.collection = [];
$scope.cidades = results.data;
$scope.collection = [].concat($scope.cidades);
}, function (err) {
$scope.message = err.error_description;
});
};
//Initializing the list
$scope.getCidades();
}]);
I really don't see anything wrong, but in any case you can add unique param for your request to prevent caching
like
$http.get(serviceBase + 'api/cidades/getall?unique=' + new Date().getTime())
Related
I am trying to displaying some data from a Mongo DB onto the front-end. I am working with the MEAN stack, which I'm relatively new at.
I have successfully gotten the data to display in JSON format at a localhost URL (localhost:3030/incidents), but cannot get the clean data to appear on the front end (which is at localhost:9000).
This is what my code looks like so far for the server side (router.js):
"use strict";
var config = require('../config/database-config');
var Router = function (options) {
var self = this;
self.environment = options.environment;
self.route = function(app) {
var IncidentController = require('./controllers/incident-controller.js');
var IncidentModel = require('./models/incident-model.js');
var incidentModel = new IncidentModel(config[`${self.environment}`]);
console.log("Incident Model", incidentModel);
var incidentController = new IncidentController({model: incidentModel});
app.get('/api/incident/:id', incidentController.findIncidentById);
app.get('/incidents', incidentController.getAllIncidents);
};
return self;
};
module.exports = Router;
Client side:
services.js:
'use strict';
angular.module('victimList.services', []).factory('Victim', function($resource) {
return $resource('http://localhost:3030/api/incident/:id');
});
data.js:
'use strict';
angular.module('victimList', [])
.service('victimList')
.controller('DataCtrl', ['victimService', function ($scope, victimService) {
victimService.getVictims(function(victims) {
$scope.victims = victims;
});
}])
.factory('victimSerivce', function($http) {
var getVictims = function(callback) {
$http.get('http://localhost:3030/incidents').success(function(data){
callback(data);
});
};
return {
getVictims: getVictims
};
});
app.js:
'use strict';
angular
.module('frontendApp', [
'ngAnimate',
'ngCookies',
'ngResource',
'ngRoute',
'ngSanitize',
'ngTouch',
'victimList',
])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl',
controllerAs: 'main'
})
.when('/victims', {
templateUrl: 'views/victims.html',
controller: 'DataCtrl',
controllerAs: 'victims'
})
.otherwise({
redirectTo: '/'
});
});
victims.html:
<div ng-app="victimList">
<h1>Testing</h1>
<div ng-controller="DataCtrl">
<ul ng-repeat="victim in victims">
<li>1</li>
<li>{{ victim.firstname }} {{ victim.lastname }}</li>
</ul>
</div>
When I navigate to the localhost:9000/victims page, I get the header tag, but no data. The console shows this error:
Error: [$injector:unpr] Unknown provider: victimServiceProvider <- victimService <- DataCtrl
What could I be missing? Thanks in advance for your help!
I figured it out! I needed to add the following:
angular.module('victimList', [])
.service('victimService')
.controller('DataCtrl', ['$scope', 'victimService', function ($scope, victimService) {
victimService.getVictims(function(victims) {
$scope.victims = victims;
});
}])
^^ Note that '$scope' was added on line 3.
I'm trying to do a simple app with ionic framework to learn how to use Firebase and manipulate data. I did everything, but my console is showing nothing. I cannot run my controller. Does anyone know what is happening?
I injected everything, at least I think I did. I guess the error is in the resolve. Is there anyone that can save me with this, please?
Here's my Controller:
(function(){
'use strict';
angular
.module('hsAdmin.users')
.controller('UsersCtrl', UsersCtrl);
UsersCtrl.$inject = ['$scope', '$state','Users' ];
function UsersCtrl($scope, $state,Users ){
var vm = angular.extend(this, {
ChangeState: ChangeState,
Users:Users
});
function ChangeState(state){
$state.go(state);
}
}
})();
Here's my Module:
(function(){
'use strict';
angular
.module('hsAdmin.users', [
'ionic',
'ngCordova',
'hsAdmin.users'
])
.config(function($stateProvider) {
$stateProvider
.state('app.users', {
url: '/users',
views: {
'menuContent': {
templateUrl: 'templates/users/users.html',
controller: 'UsersCtrl as vm'
}
}
,resolve:{
Users: function(UsersService) {
return UsersService.GetUsers().$loaded().then(function(user){
return user;
}).catch(function(error){
console.log('Error when get users: ' + error);
})
}
}
});
})
})();
Here's my Service
(function(){
'use strict';
angular
.module('hsAdmin.users')
.factory('UsersService', UsersService);
UsersService.$inject = ['fb', '$firebaseArray', '$firebaseObject','$q','$rootScope'];
function UsersService(fb, $firebaseArray, $firebaseObject,$q,$rootScope){
var service = {
GetUsers:GetUsers,
GetUsersById:GetUsersById
};
return service;
function GetUsers(){
var query = fb.child('/users');
return $firebaseArray(query);
}
function GetUsersById(id){
var query = fb.child('/users/' + id);
return $firebaseObject(query).$loaded();
}
}
})();
You are creating your hsAdmin.users module and then injecting it into itself, that is likely what is causing your problem. Try the below:
(function(){
'use strict';
angular
.module('hsAdmin.users', [
'ionic',
'ngCordova',
// 'hsAdmin.users'
])
.config(function($stateProvider) {
$stateProvider
.state('app.users', {
url: '/users',
views: {
'menuContent': {
templateUrl: 'templates/users/users.html',
controller: 'UsersCtrl as vm'
}
}
,resolve:{
Users: function(UsersService) {
return UsersService.GetUsers().$loaded().then(function(user){
return user;
}).catch(function(error){
console.log('Error when get users: ' + error);
})
}
}
});
})
})();
Try to implement controller in following way.
(function() {
'use strict';
var UsersCtrl = function($scope, $state, Users) {
var vm = angular.extend(this, {
ChangeState: ChangeState,
Users: Users
});
function ChangeState(state) {
$state.go(state);
}
}
UsersCtrl.$inject = ['$scope', '$state', 'Users'];
angular.module('hsAdmin.users').controller('UsersCtrl', UsersCtrl);
})();
First time doing an angular application, combining different tutorials but this is the first time I am trying to inject a service.
I have one of my View's controllers like:
angular.module("myApp.Pages").controller('signupController', ['$scope', '$location', '$timeout', 'authService', function ($scope, $location, $timeout, authService) {
}
however am seeing an error when I look at the Console in Developer Tools:
angular.js:12793 Error: [$injector:unpr] Unknown provider:
authServiceProvider <- authService <- signupController
http://errors.angularjs.org/1.5.0-beta.2/$injector/unpr?p0=authServiceProvider%20%3C-%20authService%20%3C-ignupController
My project structure is:
-Client
-App
-Components
-Services
-authService.js
-myAppCore.js
-Views
-app.js
-appRouting.js
-Scripts (References)
-Theme (Css)
-Index.html
My index.html scripts I add:
<!-- Angular References-->
<script src="References/Angular/angular.js"></script>
<script src="References/Angular/angular-route.js"></script>
<script src="References/Angular/angular-ui-router.min.js"></script>
<!-- End Angular References-->
<!-- my app and dependent modules -->
<script src="App/app.js"></script>
<script src="App/appRouting.js"></script>
<!-- Services -->
<script src="App/Components/Services/authService.js"></script>
<!-- END services-->
<!-- Controllers for your pages-->
<script src="App/Pages/Home/homeController.js"></script>
<script src="App/Pages/ContactUs/contactusController.js"></script>
<script src="App/Pages/Entry/entryController.js"></script>
<script src="App/Pages/Signup/signupController.js"></script>
<!-- End Controllers for the page-->
My app.js
angular.module("myApp", [
// User defined modules
'myApp.Templates', // templates
'myApp.Pages', // Pages
'myApp.Core', // Core
// Angular modules
'ui.router', // state routing
'ngRoute', // angular routing
'angular-loading-bar', //loading bar
'LocalStorageModule', //local browser storage
])
and appRouting.js
angular.module("myApp")
.config(["$stateProvider", function ($stateProvider) {
$stateProvider.state('Home', {
url: '/Home',
templateUrl: 'App/Pages/Home/home.html',
controller: 'homeController'
})
.state('Entry', {
url: '/Entry',
templateUrl: 'App/Pages/Entry/entry.html',
controller: 'entryController'
})
.state('Signup', {
url: '/Signup',
templateUrl: 'App/Pages/Signup/signup.html',
controller: 'signupController'
})
.state('Contactus', {
url: '/Contactus',
templateUrl: 'App/Pages/ContactUs/contactus.html',
controller: 'contactusController'
})
.state("otherwise", {
url: "*path",
templateUrl: "App/Pages/NotFound/notFound.html"
});
}])
.run(["$location", function ($location) {
// Go to state dashboard
$location.url('/Home');
}]);
authService which handles login/register:
app.factory('authService', ['$http', '$q', 'localStorageService', function ($http, $q, localStorageService) {
var serviceBase = '<location>';
var authServiceFactory = {};
var _authentication = {
isAuth: false,
userName: ""
};
var _saveRegistration = function (registration) {
_logOut();
return $http.post(serviceBase + 'api/account/register', registration).then(function (response) {
return response;
});
};
var _login = function (loginData) {
var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
var deferred = $q.defer();
$http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {
localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
_authentication.isAuth = true;
_authentication.userName = loginData.userName;
deferred.resolve(response);
}).error(function (err, status) {
_logOut();
deferred.reject(err);
});
return deferred.promise;
};
var _logOut = function () {
localStorageService.remove('authorizationData');
_authentication.isAuth = false;
_authentication.userName = "";
};
var _fillAuthData = function () {
var authData = localStorageService.get('authorizationData');
if (authData) {
_authentication.isAuth = true;
_authentication.userName = authData.userName;
}
}
authServiceFactory.saveRegistration = _saveRegistration;
authServiceFactory.login = _login;
authServiceFactory.logOut = _logOut;
authServiceFactory.fillAuthData = _fillAuthData;
authServiceFactory.authentication = _authentication;
return authServiceFactory;
}]);
myAppPages.js and myAppCore.js are the same just their respective names :
angular.module("myApp.Pages", []);
Edit: Seeing a "app is not defined" reference error in authService
You don't defined var app, so use angular.module("myApp") to define your factory
angular.module("myApp").factory('authService', ['$http', '$q', 'localStorageService', function ($http, $q, localStorageService)
Also you can declare var app = angular.module("myApp") and use app
I simply did not declare:
var app = angular.module(...)
And my service was referencing app when that did not exist.
I am starting out on the angular seed. I have a json file that displays items like the below.
{
"id":"1",
"name":"Spain",
"abbrev":"esp"
}
When I click on a country in the list I want to the display the details such as the name for this item.
I have this working as shown below.
/* app.js */
'use strict';
// Declare app level module which depends on views, and components
angular.module('myApp', ['ngRoute','myApp.controllers','myApp.services'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/', {
templateUrl: 'templates/view1.html',
controller: 'CountryCtrl'
});
}])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/:name', {
templateUrl: 'templates/view2.html',
controller: 'CountryCtrl'
});
}])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.otherwise({redirectTo: '/'});
}]);
/* services.js */
angular.module('myApp.services', [])
.factory('Countries', ['$http', function($http) {
var Countries = {};
Countries.name = '';
Countries.listCountries = function () {
return $http.get('../api/countries');
},
Countries.ChangeName = function (value) {
Countries.name = value;
}
return Countries;
}]);
/* controllers.js */
angular.module('myApp.controllers', [])
.controller('CountryCtrl', ['$scope', 'Countries', '$location', function($scope, Countries,$location) {
listCountries();
function listCountries() {Countries.listCountries()
.success(function (data, status, headers, config) {
$scope.countries = data.countries;
})
.error(function(data, status, headers, config) {
$scope.status = 'Unable to load data: ' + error.message;
});
}
$scope.name = Countries.name;
$scope.changeView = function(countryName,indx){
$location.path(countryName);
$scope.name = Countries.ChangeName(countryName);
}
}]);
/* templates/view1.html */
<ul>
<li ng-repeat="country in countries">
<div ng-click="changeView(country.name,$index)">{{country.name}}</div>
</li>
</ul>
/* templates/view2.html */
{{name}}
What I can't get to work is that if I go to http://www.example.com/app/#/ then navigate to spain in the list then I get taken to http://www.example.com/app/#/esp and {{name}} gets outputted as esp.
However if I navigate straight to http://www.example.com/app/#/esp without first clicking on spain in the list I get no value in my $scope.name
How can I achieve this?
I want the name to also be set based on the location path if it is available.
I know that $location.$$path will get me /esp however I don't really think this is the best idea to use this incase the url builds out to something bigger eg http://www.example.com/app/#/esp/events
can I some how access the index or id of the item so that I can then access the data like
{{countries[0].name}}
where 0 is id of esp - 1.
What is the best approach?
Mate, there are a couple of issues with your app.
Your service retains "state" although is only used to retrieve information
You're using the same controller to 2 different views (bad practice)
$scope.status = 'Unable to load data: ' + error.message; --> Error is not defined
There are a couple of js errors too, like strayed commas and stuff
Anyways, here's a revised version of your code. Fiddle
// Instantiate your main module
var myApp = angular.module('myApp', ['ngRoute']);
// Router config
myApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'templates/view1.html',
controller: 'CountryListCtrl'
})
.when('/:id', {
templateUrl: 'templates/view2.html',
controller: 'CountryCtrl'
})
}
]);
// Your Factory. Now returns a promise of the data.
myApp.factory('Countries', ['$q',
function($q) {
var countriesList = [];
// perform the ajax call (this is a mock)
var getCountriesList = function() {
// Mock return json
var contriesListMock = [{
"id": "0",
"name": "Portugal",
"abbrev": "pt"
}, {
"id": "1",
"name": "Spain",
"abbrev": "esp"
}, {
"id": "2",
"name": "Andora",
"abbrev": "an"
}];
var deferred = $q.defer();
if (countriesList.length == 0) {
setTimeout(function() {
deferred.resolve(contriesListMock, 200, '');
countriesList = contriesListMock;
}, 1000);
} else {
deferred.resolve(countriesList, 200, '');
}
return deferred.promise;
}
var getCountry = function(id) {
var deferred = $q.defer();
if (countriesList.length == 0) {
getCountriesList().then(
function() {
deferred.resolve(countriesList[id], 200, '');
},
function() {
deferred.reject('failed to load countries', 400, '');
}
);
} else {
deferred.resolve(countriesList[id], 200, '');
}
return deferred.promise;
}
return {
getList: getCountriesList,
getCountry: getCountry
};
}
]);
//Controller of home page (pretty straightforward)
myApp.controller('CountryListCtrl', ['$scope', 'Countries',
function($scope, Countries) {
$scope.title = 'Countries List';
$scope.countries = [];
$scope.status = '';
Countries.getList().then(
function(data, status, headers) { //success
$scope.countries = data;
},
function(data, status, headers) { //error
$scope.status = 'Unable to load data:';
}
);
}
]);
// controller of Country page
// Notice how we use $routeParams to grab the "id" of our country from the URL
// And use our service to look for the actual country by its ID.
myApp.controller('CountryCtrl', ['$scope', '$routeParams', 'Countries',
function($scope, $routeParams, Countries) {
$scope.country = {
id: '',
name: '',
abbrev: ''
};
var id = $routeParams.id;
Countries.getCountry(id).then(
function(data, status, hd) {
console.log(data);
$scope.country = data;
},
function(data, status, hd) {
console.log(data);
}
);
}
]);
In your "CountryCtrl", if you include $routeParams and use $routeParams.tlaname, you will have access to the tlaname. You can then use that to initialize your data.
Lets say i list all users in a list, when i click a user i want to route to a new view and get the data for the selected person.
What is the preferred way? Should i move the data i already got when i listed the users or should i create a new server call?
My first thought is to pass the data, but the problem with this is that the data the gets lost if the user refreshes the page.
What is the best practice to solve this?
Small example:
(function() {
var app = angular.module('app');
var controllerId = 'app.controllers.views.userList';
app.controller(controllerId, [
'$scope', 'UserService',function ($scope, userService) {
var vm = this;
vm.users = [];
userService.getAllUsers().success(function (data) {
vm.users= data.users;
});
var gotoUser = function(user) {
// Pass the user to UserDetail view.
}
}
]);
})();
<div data-ng-repeat="user in vm.users" ng-click="vm.gotoUser(user)">
<span>{{customer.firstname}} {{customer.lastname}}</span>
</div>
i now list the user details in UserDetail view, this view is now vulnerable against a browser refresh.
Typically most people just create a new server call, but I'll assume you're worried about performance. In this case you could create a service that provides the data and caches it in local storage.
On controller load, the controller can fetch the data from the service given the route params and then load the content. This will achieve both the effect of working on page refresh, and not needing an extra network request
Here's a simple example from one of my apps, error handling left out for simplicity, so use with caution
angular.
module('alienstreamApp')
.service('api', ['$http', '$q','$window', function($http, $q, $window) {
//meta data request functions
this.trending = function() {
}
this.request = function(url,params) {
var differed = $q.defer();
var storage = $window.localStorage;
var value = JSON.parse(storage.getItem(url+params))
if(value) {
differed.resolve(value);
} else {
$http.get("http://api.alienstream.com/"+url+"/?"+params)
.success(function(result){
differed.resolve(result);
storage.setItem(url+params,JSON.stringify(result))
})
}
return differed.promise;
}
}]);
I would say that you should start off simple and do a new server call when you hit the new route. My experience is that this simplifies development and you can put your effort on optimizing performance (or user experience...) where you will need it the most.
Something like this:
angular.module('app', ['ngRoute', 'ngResource'])
.factory('Users', function ($resource) {
return $resource('/api/Users/:userid', { userid: '#id' }, {
query: { method: 'GET', params: { userid: '' }, isArray: true }
});
});
.controller("UsersController",
['$scope', 'Users',
function ($scope, Users) {
$scope.loading = true;
$scope.users = Users.query(function () {
$scope.loading = false;
});
}]);
.controller("UserController",
['$scope', '$routeParams', 'Users',
function ($scope, $routeParams, Users) {
$scope.loading = true;
$scope.user = Users.get({ userid: $routeParams.userid }, function () {
$scope.loading = false;
});
$scope.submit = function () {
$scope.user.$update(function () {
alert("Saved ok!");
});
}
}]);
.config(
['$routeProvider', '$locationProvider',
function ($routeProvider, $locationProvider) {
$routeProvider
.when('/users', {
templateUrl: '/users.html',
controller: 'UsersController'
})
.when('/users/:userid', {
templateUrl: '/user.html',
controller: 'UserController'
})
.otherwise({ redirectTo: '/users' });
}
]
);