adding resolver to angular routeProvider in config - angularjs

i start working with angular 1.x boilerplate and have 1 problem, i can`t send into resolver promise from service
function ExampleService($http) {
'ngInject';
const service = {};
let getTasks = ()=> {
return $http.get('tasks');
};
service.isReady = new Promise((resolve, reject)=> {
getTasks().then(
(data) => {
resolve(data);
},
(err, status) => {
reject(err, status);
});
});
return service;
}
export default {
name: 'ExampleService',
fn: ExampleService
};
But when i try inject ,y service to on_config.js i have error
Uncaught Error: [$injector:modulerr] Failed to instantiate module app due to:
Error: [$injector:unpr] Unknown provider: ExampleService
My stateProvider
$stateProvider
.state('Home', {
url: '/',
controller: 'ExampleCtrl as home',
templateUrl: 'home.html',
title: 'Home',
resolve:{example:ExampleService.isReady}
})
Maybe i do something wrong or you can suggest how can i impelemt logic for preloading some data to app before rendering first controller
P.S. link to bolerplate

Services can't be injected into config blocks. They need to be injected in resolver functions:
$stateProvider
.state('Home', {
url: '/',
controller: 'ExampleCtrl as home',
templateUrl: 'home.html',
title: 'Home',
resolve:{
example: function (ExampleService) {
return ExampleService.isReady();
}
})
Also the isReady needs to be a function, not a new promise:
service.isReady = () => {
return getTasks().then(response => response.data);
}

Related

Call on $state.go not working in unit test

I work on an app based on Angular 1.5, angular-ui-router and WebPack for which I want to make unit tests on module declaration part, especially on state configuration (I want to test source code of resolve part).
All others unit tests of my app are working fine but on this one it looks like my call $state.go are never processed:
describe('Simple Module', () => {
beforeEach(angular.mock.module('ui.router', 'my-app'));
let $state;
let $location;
let $httpBackend;
beforeEach(inject((_$location_, _$state_, _$httpBackend_) => {
$state = _$state_;
$location = _$location_;
$httpBackend = _$httpBackend_;
}));
describe('app.onlineListing.error', () => {
it('go to state', () => {
const state = 'app.onlineListing.error';
$state.go(state);
// PROBLEM IS HERE...
// $state.current.name is empty ('') just like if $state.go was never called
// It's not better with $location.url and $httpBackend.flush
// ...
expect($state.current.name).toBe(state);
// I will spy on myService and expect that myService.getData has been called
// but currently state is not reach so resolve parts are never triggered...
});
});
});
Here is my app module:
export default angular.module('my-app', ['oc.lazyLoad', 'ui.router', mySimpleModule.name])
.config(($stateProvider, ...) => {
...
$stateProvider
.state('app', {
abstract: true,
...
}
});
There is mySimpleModule declaration:
export default angular.module('my-simple-module', [
'ui.router'
])
.config(($stateProvider) => {
$stateProvider
.state('app.onlineListing', {
url: '/onlineListing',
abstract: true,
views: {
body: {
template: '<ui-view />'
}
}
})
.state('app.onlineListing.error', {
url: '/error',
template: require('./configurationError/configurationError.html'),
controller: 'onlineListingConfigurationErrorCtrl',
controllerAs: 'controller',
resolve: {
// #ngInject
modules: ($q, $ocLazyLoad) => {
return $q((resolve) => {
require(['./configurationError/configurationError.js'], (module) => {
resolve($ocLazyLoad.load({ name: module.default }));
});
});
},
fetchedData: (myService) => {
// Finally I want my test to check if getData is called
return myService.getData();
}
}
})
});
Edit
I also try this tutorial (which is exactly what I try to achieve) but it's not working better.

AngularJS controller managing in MEAN-stack develop

I am a Web Developer with experience over 5 years. Nowadays I learnt MEAN-stack web site developing way and began to start MEAN-stack project. Then I have some problems in front-end section(angular control managing).
My main problem is my angular controller js file causes 2 browser error. like as following.
The first error is as follows:
aangular.js:68 Uncaught Error: [$injector:nomod] Module 'app' is not available!
You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.(…)(anonymous function)
# angular.js:68(anonymous function)
# angular.js:2082ensure
# angular.js:2006module
# angular.js:2080(anonymous function)
# UsersService.js:4(anonymous function)
# UsersService.js:111
The second error is as follows:
angular.js:13920 Error: [ng:areq] Argument 'Users.Controller' is not a function, got undefined
My front-end code structure is the following.
controllers
users.controller.js, account.controller.js, projects.controller.js and so on.
services
UsersService.js, AccountService.js and so on
app.js (middleware section)
views
index.html, htmls corresponding to each controller js
lets take a look code in detail.
App.js file:
(function () {
angular.module('app', ['ui.router'])
.config(config)
.run(run);
function config($stateProvider, $urlRouterProvider) {
// default route
$urlRouterProvider.otherwise("/");
$stateProvider
.state('home', {
url: '/',
template: '<h1>Unpasan Admin Page!</h1>',
controller: 'Users.Controller',
controllerAs: 'vm',
//data: { activeTab: 'home' }
})
.state('account', {
url: '/account',
templateUrl: 'views/account.html',
controller: 'Accounts.Controller',
controllerAs: 'vm',
data: { activeTab: 'account' }
})
.state('client', {
url: '/client',
templateUrl: 'views/client.html',
controller: 'Clients.Controller',
controllerAs: 'vm',
data: { activeTab: 'client' }
})
.state('user', {
url: '/user',
templateUrl: 'views/user.html',
controller: 'Users.Controller',
controllerAs: 'vm',
data: { activeTab: 'client' }
})
.state('project', {
url: '/project',
templateUrl: 'views/project.html',
controller: 'Projects.Controller',
controllerAs: 'vm',
data: { activeTab: 'project' }
});
}
UsersService.js:
(function () {
angular
.module('app')
.factory('UserService', function(){
var service = {};
service.GetCurrent = GetCurrent;
service.GetAll = GetAll;
service.GetById = GetById;
service.GetByUsername = GetByUsername;
service.Create = Create;
service.Update = Update;
service.Delete = Delete;
return service;
function GetCurrent() {
return $http.get('/api/users/current').then(handleSuccess, handleError);
}
function GetAll() {
return $http.get('/api/users').then(handleSuccess, handleError);
}
function GetById(_id) {
return $http.get('/api/users/' + _id).then(handleSuccess, handleError);
}
function GetByUsername(username) {
return $http.get('/api/users/' + username).then(handleSuccess, handleError);
}
function Create(user) {
return $http.post('/api/users', user).then(handleSuccess, handleError);
}
function Update(user) {
return $http.put('/api/users/' + user._id, user).then(handleSuccess, handleError);
}
function Delete(_id) {
return $http.delete('/api/users/' + _id).then(handleSuccess, handleError);
}
// private functions
function handleSuccess(res) {
return res.data;
}
function handleError(res) {
return $q.reject(res.data);
}
});
})();
users.controller.js
angular.module('app',[]).controller('UsersController', ['$scope, UserService', function($scope, UserService){
$scope.users = null;
initController();
console.log('Users.Controller:initController');
function initController() { // get current user
UserService.getAllUser().then(function (users) {
$scope.users = users;
});
}
function saveUser() {
UserService.Update(vm.user)
.then(function () {
FlashService.Success('User updated');
})
.catch(function (error) {
FlashService.Error(error);
});
}
function deleteUser() {
UserService.Delete(vm.user._id)
.then(function () {
// log user out
$window.location = '/login';
})
.catch(function (error) {
FlashService.Error(error);
});
}
}] );
When I clicked elements of sidebar in index.html, should be exchanged content of 'ui-view' tag.
The error message mentioned above is case of clicked users 'ui tag'.
Instead of controller: 'Users.Controller', it should be controller: 'UsersController' (see object passed into the state definition for 'home'). You should pass in the name of the controller (UsersController), not the file name (users.controller).

Get DB Value In Angular Config

I have an app that uses angular. In the app.config is where I have to setup my routes, however I want to authorize my routes because not everyone who uses the app can see every page.
So I have already tried to make a factory that gives a boolean to tell the app if that person can see the route or not, and learned that I cannot inject a factory into a config.
So I have made a provider that I can inject into the config:
(function () {
'use strict';
angular.module('services')
.factory('Auth', ['$http', function AuthFactory($http) {
return {
LinkAuth: function (Name) {
return $http({ method: 'GET', url: '/Dashboard/AuthorizeNavItem', data: { Name: Name } });
}
}
}]);
angular.module('services')
.provider('AuthProvider', ['Auth', function (Auth) {
var allowed = false;
this.$get = function (Name) {
Auth.LinkAuth(Name).success(function (data) {
allowed = data.Authorized;
});
return allowed;
}
}]);
})();
My app.config:
(function () {
'use strict';
angular.module('app.it', [])
.config(['$stateProvider', 'msNavigationServiceProvider', 'AuthProvider', function ($stateProvider, msNavigationServiceProvider, AuthProvider) {
$stateProvider
.state('app.it', {
abstract: true,
url: '/information-technology',
})
.state('app.it.users', {
url: '/users',
views: {
'content#app': {
templateUrl: '/IT/Users',
controller: 'ITUserController as vm'
}
}
});
/*
We need to get a bool to say if a user is part of a group that can see this page.
*/
var allowed = true;//I want the provider $get method to return that bool here
if (allowed)
{
//This builds the navigation bar
msNavigationServiceProvider.saveItem('app.authroute', {
title: 'Authorized Route',
icon: 'icon-monitor',
weight: 2
});
//This builds the navigation bar
msNavigationServiceProvider.saveItem('app.authroute.route', {
title: 'Route',
state: 'app.authroute.route'
});
}
}]);
})();
How do I access that AuthProvider $get and store the bool in a variable in the config?

Angular Component/Controller resolve $stateprovider

I am trying to adapt to Angular's component (from code generated by Angular Fullstack Generator).
I tried to configure the routes to resolve "query" as per below:
angular.module('paizaApp')
.config(function($stateProvider) {
$stateProvider
.state('main', {
url: '/',
template: '<main query="$resolve.query"></main>',
resolve:{
query:function(){return null;}
},
.state('starred',{
url:'/users/:userId/starred',
template: '<main query="$resolve.query"></main>',
resolve:{
query:function($stateParams){
return {stars:$stateParams.userId};
}
}
})
.state('users',{
url:'/users/:userId',
template: '<main query="$resolve.query"></main>',
resolve:{
query:function($stateParams){
return {user:$stateParams.userId}
}
}
The following are the codes for the controller/component.
class MainController {
constructor($http, $scope, socket, Auth, query) {
this.$http = $http;
this.socket = socket;
this.awesomeThings = [];
$scope.isLoggedIn = Auth.isLoggedIn;
$scope.getCurrentUser = Auth.getCurrentUser;
$onInit() {
this.$http.get('/api/things',{params:{query:query}})
.then(response => {
this.awesomeThings = response.data;
this.socket.syncUpdates('thing', this.awesomeThings);
});
}////////
////////////////////////////////////// etc..
angular.module('paizaApp')
.component('main', {
templateUrl: 'app/main/main.html',
bindings:{query:'='},
controller: MainController
});
I am getting an error message - unknown query provider. However if I remove query from the constructor then the error message is "query is not defined".
Can you please see where I have gone wrong and whether I am supposed to inject the "query" variable into the controller? I am new to Angular 1, not to mention Angular 2.
Update: I have also tried something like this but didn't work:
angular.module('paizaApp')
.config(function($stateProvider) {
$stateProvider
.state('main', {
url: '/',
template: '<main></main>',
resolve:{
query:function(){return null;}
},
controller:function($scope,query){
$scope.query=query
}
And:
angular.module('paizaApp')
.component('main', {
templateUrl: 'app/main/main.html',
controller: MainController,
scope:{query:'='}
});
You shouldn't inject query on controller constructor. You could have do that if you have specified MyController as controller for state.
The query resolve is already passed in component bindings. You can directly get the value of query resolve inside this.query

Using controllerAs with $resource in AngularJs

I am working on an application and I'd like to use the controllerAs syntax to not rely only on $scope. I am using $resource to get data from the API and the problem I encounter is that in the success/error callbacks I can use only $scope, since this is not defined.
Here is some code to better explain the problem.
This is my main module where among other things I configure the router:
angular
.module('app', ['ngRoute', 'ngResource', 'LocalStorageModule', 'app.users', 'app.auth'])
.config(configure)
.controller('MainController', ['$scope', '$location', MainController]);
function configure($routeProvider, localStorageServiceProvider, $resourceProvider) {
// configure the router
$routeProvider
.when('/', {
templateUrl: 'app/homepage.html',
controller: 'MainController',
controllerAs: 'vm',
data: { authRequired: true }
})
.when('/users', {
templateUrl: 'app/users/main.html',
controller: 'UserController',
controllerAs: 'vmu',
data: { authRequired: true }
})
.otherwise({redirectTo: '/'});
}
// the MainController is not relevant here
In the user module I get some info about the users from the API. Here is a simplified example:
angular
.module('app.users', ['ngResource'])
.controller('UserController', ['UserService', UserController])
.factory('UserService', ['$resource', UserService]);
function UserController(UserService) {
this.users = UserService.users.list();
this.getUserInfo = function(userId) {
this.user = UserService.users.single({ id: userId },
function(success) {
// here I'd like to use 'this' but the following line will trigger an error
this.groupRules = UserService.users.rules({ id: success.userGroupId });
// I have to use $scope instead but it is not what I want
// $scope.groupRules = UserService.users.rules({ id: success.userGroupId });
} );
}
}
function UserService($resource) {
var userResource = {};
userResource.users = $resource('https://my.api.com/users/:action',
{},
{
list: { method: 'GET', isArray: true, params: { action: 'list' } }
single: { method: 'GET', params: { action: 'single', id: '#id' } }
rules: { method: 'GET', params: { action: 'getRules', id: '#id' } }
});
return userResource;
}
I'd like to be able to use 'this' in the callback of the $resource, but of course I'll get an error since 'this' is 'undefined' inside the callback.
Using $scope solves the problem, but I need to refactor some code and I'd like to avoid using $scope all the time.
Any workaround? Maybe I should use a different approach?
Thanks in advance for your help and explanations!
You should look into how to use this in javascript and into javascript scopes and closures.
This should work better:
function UserController(UserService) {
var _this = this;
this.users = UserService.users.list();
this.getUserInfo = function(userId) {
_this.user = UserService.users.single({ id: userId },
function(success) {
// here I'd like to use 'this' but the following line will trigger an error
_this.groupRules = UserService.users.rules({ id: success.userGroupId });
} );
}
}

Resources