I am working with angular.js and satelizer to do JWT Authentication on a REST API.
The authentication works fine and the page is sending the authorization header within 3 states. Here is my state provider:
$stateProvider
.state('auth', {
url: '/auth',
templateUrl: '/views/login.html',
controller: 'AuthController as auth'
})
.state('dashboard', {
url: '/dashboard',
templateUrl: '/views/dashboard.html',
controller: 'DashboardController as dash'
})
.state('mitglieder', {
url: '/mitglieder',
templateUrl: '/views/mitglieder.html',
controller: 'MitgliederController as mitglieder'
})
.state('neuesMitglied', {
url: '/neuesMitglied',
templateUrl: '/views/neuesMitglied.html',
controller: 'NewMitgliederController as newMitglied'
})
.state('users', {
url: '/users',
templateUrl: '/views/main.html',
controller: 'UserController as user'
});
});
But however, inside the state 'neuesMitglied' it suddenly does no longer send the authorization header and gets rejected by the rest api. My NewMitgliederController looks like this:
(function() {
'use strict';
angular
.module('authApp')
.controller('NewMitgliederController', NewMitgliederController);
function NewMitgliederController($auth, $state, $http, $rootScope, $scope) {
var vm = this;
vm.error;
//vm.toAdd;
//vm.rawImage;
//Fetched Data
vm.fetchedData;
var fetchData = function() {
$http.get('APIv1/Beitragsgruppen/list/').success(function (data) {
vm.fetchedData.mitgliedsgruppen = data;
}).error(function (error) {
vm.error = error;
});
}
angular.element(document).ready( function(){
$('#mainNav ul, #mainNav li').removeClass('active');
$('#mitgliederNav').addClass('active');
fetchData();
} );
}
})();
Why is it not working inside this controller but in all other controllers, the $http.get ist working with authorization header?
EDIT
I tracked this behavior a little bit and found that something is removing the "Authorization" Header which has been set by the satellizer interceptor (for this controller request the method is fired and this header is really added by satellizer interceptor but it is getting removed afterwards and I dont't know where because I do not touch any header data or have own interceptors)... Is it a bug?
Try this one:
(function() {
'use strict';
angular
.module('authApp')
.controller('NewMitgliederController', NewMitgliederController);
function NewMitgliederController($http, $scope) {
var vm = this;
vm.error = {};
vm.fetchedData = {};
fetchData();
function fetchData() {
$http.get('APIv1/Beitragsgruppen/list/').then( function(res) {
vm.fetchedData.mitgliedsgruppen = res;
$('#mainNav ul, #mainNav li').removeClass('active');
$('#mitgliederNav').addClass('active');
}, function(err) {
vm.error = err;
});
}
}
})();
Related
I have an angular app that needs to do a quick http request to get some config information before the rest of the application is initiated, at least before the controllers. Looked into using $UrlRouterProvider, but I did not figure out how to make the app wait for the http be done.
What I need to be finished:
$http({method: 'GET', url: '/config'}).then(function(res) {
configProvider.setConfig(res.data.config);
}
You can create a separate js file where you can make http request and then initialize/bootstrap your app via js code instead of ng-app in html code.
Refer the below code:
(function() {
var application, bootstrapApplication, fetchData;
application = angular.module('app');
fetchData = function() {
var $http, initInjector;
initInjector = angular.injector(['ng']);
$http = initInjector.get('$http');
$http.get('<url>');
};
bootstrapApplication = function() {
angular.element(document).ready(function() {
angular.bootstrap(document, ['app']);
});
};
fetchData().then(bootstrapApplication);
})();
I hope it helps.
Resolve must be declared on state, not on the view
change
.state('app', {
abstract: true,
url:'/',
views: {
"content": {
templateUrl: "myurl.html"
},
resolve {
myVar: ['$http', 'myService', function($http, myService) {
return $http({method: 'GET', url:'url'})
.then(function(res) { //do stuff })
to
.state('app', {
abstract: true,
url:'/',
views: {
"content": {
templateUrl: "myurl.html"
}
},
resolve {
myVar: ['$http', 'myService', function($http, myService) {
return $http({method: 'GET', url:'url'})
.then(function(res) { //do stuff })...
Very simply, after an API call, depending on the return value, how is the appropriate view loaded? Consider having
search.html
views/found.html
views/notfound.html
Search's controller makes an AJAX call to a service and gets a good or bad result. Now I want the appropriate view to load, without user having to click. I just can't figure out how to do this and have looked at scores of routing/view examples. I'm using HTML5 mode.
app.config(['$routeProvider', '$locationProvider',
function ($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: 'search.html',
controller: 'searchCtrl'
})
.when('found', {
templateUrl: 'views/found.html',
controller: 'foundCtrl'
})
.when('notFound', {
templateUrl: 'views/notFound.html',
controller: 'notFoundCtrl'
})
.otherwise({
templateUrl: 'search.html',
controller: 'searchCtrl'
});
$locationProvider.html5Mode({
enabled: true,
requiredBase: true
});
And in the controller ..
$scope.post = function (requestType, requestData) {
var uri = 'Search/' + requestType;
$http.post(uri, requestData)
.success(function (response) {
$scope.searchResult.ID = response.ID;
$scope.searchResult.Value = response.Value;
// how is the view/route loaded without a user click?
'found';
return true;
}).error(function (error) {
// how is the view/route loaded without a user click?
'notFound';
return false;
});
I'm just lost after getting back the response on how to invoke a view within the template.
Since you are using ngRoute use $location.path() instead of $state.go(). The $location.path() method accepts a url specified in route configuration. E.g.:
$location.path('/found');
Say your controller is AppController, then the complete code will look something like:
angular.module('app', ['ngRoute'])
.controller('AppController', function ($location, $http) {
$scope.post = function (requestType, requestData) {
var uri = 'Search/' + requestType;
$http.post(uri, requestData)
.success(function (response) {
$scope.searchResult.ID = response.ID;
$scope.searchResult.Value = response.Value;
// how is the view/route loaded without a user click?
$location.path('/found');
}).error(function (error) {
// how is the view/route loaded without a user click?
$location.path('/notFound');
});
});
Refer https://docs.angularjs.org/api/ng/service/$location for api documentation of $location.path
Right now i am making an AngularJS+UI router install application. But i have a problem, the problem is, that i want to disable access to the views, associated with the install application. I want to do it in resolve in the state config.
But the problem is i need to get the data from a RESTful API, whether the application is installed or not. I tried making the function, but it loaded the state before the $http.get request was finished.
Here was my code for the resolve function:
(function() {
var app = angular.module('states', []);
app.run(['$rootScope', '$http', function($rootScope, $http) {
$rootScope.$on('$stateChangeStart', function() {
$http.get('/api/v1/getSetupStatus').success(function(res) {
$rootScope.setupdb = res.db_setup;
$rootScope.setupuser = res.user_setup;
});
});
}]);
app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/404");
$stateProvider.state('db-install', {
url: "/install/db",
templateUrl: 'admin/js/partials/db-install.html',
controller: 'DBController',
resolve: {
data: function($q, $state, $timeout, $rootScope) {
var setupStatus = $rootScope.setupdb;
var deferred = $q.defer();
$timeout(function() {
if (setupStatus === true) {
$state.go('setup-done');
deferred.reject();
} else {
deferred.resolve();
}
});
return deferred.promise;
}
}
})
.state('user-registration', {
url: "/install/user-registration",
templateUrl: "admin/js/partials/user-registration.html",
controller: "RegisterController"
})
.state('setup-done', {
url: "/install/setup-done",
templateUrl: "admin/js/partials/setup-done.html"
})
.state('404', {
url: "/404",
templateUrl: "admin/js/partials/404.html"
});
}]);
})();
EDIT:
Here is what my ajax call returns:
Try this way:
$stateProvider.state('db-install', {
url: "/install/db",
templateUrl: 'admin/js/partials/db-install.html',
controller: 'DBController',
resolve: {
setupStatus: function($q, $state, $http) {
return $http.get('/api/v1/getSetupStatus').then(function(res) {
if (res.db_setup === true) {
$state.go('setup-done');
return $q.reject();
}
return res;
});
}
}
})
Then inject setupStatus in controller:
.state('setup-done', {
url: "/install/setup-done",
templateUrl: "admin/js/partials/setup-done.html",
controller: ['$scope', 'setupStatus', function ($scope, setupStatus) {
$scope.setupdb = setupStatus.db_setup;
$scope.setupuser = setupStatus.user_setup;
}]
})
I am creating a mobile app in AngularJS. I call a resource that calls an API to give me values. Everything works fine, but with slow connections or 3G $ scope not cool me, and therefore when browsing the list of items is old.
SERVICES.JS
.factory('Exercises', function($resource) {
// localhost: Local
// 79.148.230.240: server
return $resource('http://79.148.230.240:3000/wodapp/users/:idUser/exercises/:idExercise', {
idUser: '55357c898aa778b657adafb4',
idExercise: '#_id'
}, {
update: {
method: 'PUT'
}
});
});
CONTROLLERS
.controller('ExerciseController', function($q, $scope, $state, Exercises) {
// reload exercises every time when we enter in the controller
Exercises.query(function(data) {
$scope.exercises = data;
});
// refresh the list of exercises
$scope.doRefresh = function() {
// reload exercises
Exercises.query().$promise.then(function(data) {
$scope.exercises = data;
}, function(error) {
console.log('error');
});
// control refresh element
$scope.$broadcast('scroll.refreshComplete');
$scope.$apply();
}
// create a new execersie template
$scope.newExercise = function() {
$state.go('newExercise');
};
// delete a exercise
$scope.deleteExercise = function(i) {
// we access to the element using index param
var exerciseDelete = $scope.exercises[i];
// delete exercise calling Rest API and later remove to the scope
exerciseDelete.$delete(function() {
$scope.exercises.splice(i, 1);
});
};
})
APP.js
angular.module('wodapp', ['ionic', 'ngResource', 'wodapp.controllers','wodapp.services'])
// Run
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// ionic is loaded
});
})
// Config
.config(function($stateProvider, $urlRouterProvider, $ionicConfigProvider) {
$stateProvider
.state('slide', {
url: '/',
templateUrl: 'templates/slides.html',
controller: 'SlideController'
})
.state('login', {
url: '/login',
templateUrl: 'templates/login.html',
controller: 'LoginController'
})
.state('dashboard', {
url: '/dashboard',
templateUrl: 'templates/dashboard.html',
controller: 'DashboardController'
})
.state('exercise', {
url: '/exercise',
templateUrl: 'templates/exercises.html',
controller: 'ExerciseController'
})
.state('newExercise',{
url: '/newExercise',
templateUrl: 'templates/newExercise.html',
controller: 'NewExerciseController'
});
$urlRouterProvider.otherwise('/');
});
If you want to reload a part of your controller logic, every time the view is activated:
.controller('ExerciseController', function(
$q,
$scope,
$state,
Exercises,
$ionicView
) {
// reload exercises every time when we enter in the controller
$ionicView.enter(function(){
// This gets executed regardless of ionicCache
Exercises.query(function(data) {
$scope.exercises = data;
});;
});
});
Else, you can use the reload option on .state()
i am just learning basics of angular and today it started to change my app using a factory to get data and implementing route provider ! So far everything works fine! But when I try to add data on another view and head back to my list view scope is reloaded again from factory and no added data shows up.
My approach won't work because each time change my view I will call my controller which reloads data from factory! What can I do to make my Add template will work and changes data everywhere else too.
Maybe somebody can give me a tip how to cope with this problem ?
script.js
var app = angular.module('printTrips', ['ngRoute']);
app.factory('tripFactory', function($http) {
return{
getTrips : function() {
return $http({
url: 'trips.json',
method: 'GET'
})
}
}
});
app.controller('TripController', function($scope, $filter, tripFactory) {
$scope.trips = [];
tripFactory.getTrips().success(function(data){
$scope.trips=data;
var orderBy = $filter('orderBy');
$scope.order = function(predicate, reverse) {
$scope.trips = orderBy($scope.trips, predicate, reverse)};
$scope.addTrip = function(){
$scope.trips.push({'Startdate':$scope.newdate, DAYS: [{"DATE":$scope.newdate,"IATA":$scope.newiata,"DUTY":$scope.newduty}]})
$scope.order('Startdate',false)
$scope.newdate = ''
$scope.newiata = ''
$scope.newduty = ''
}
$scope.deleteTrip = function(index){
$scope.trips.splice(index, 1);
}
});
});
view.js
app.config(function ($routeProvider){
$routeProvider
.when('/',
{
controller: 'TripController',
templateUrl: 'view1.html'
})
.when('/view1',
{
controller: 'TripController',
templateUrl: 'view1.html'
})
.when('/view2',
{
controller: 'TripController',
templateUrl: 'view2.html'
})
.when('/addtrip',
{
controller: 'TripController',
templateUrl: 'add_trip.html'
})
.otherwise({ redirectTo: 'View1.html'});
});
Here is my plunker
Thanks for your help
You should use Service instead of Factory.
Services are loaded each time they are called. Factory are just loaded once.
app.service('tripFactory', function($http) {
return{
getTrips : function() {
return $http({
url: 'trips.json',
method: 'GET'
})
}
}
});