I am having issues trying to access a service on a controller. The issue happen when the Ordenes services is called. How I can call a service with two parameter using values from the scope from a controller using ui-router?
I have the same code working but without the use of ui-router. It seems like the code is not loading properly the service inside the Controller.
App.js
'use strict';
app = angular.module('logica-erp', [
'ngCookies',
'ngResource',
'ngSanitize',
'ui.router',
'authorization',
'ui.router.stateHelper',
'logica-erp.kds',
'logica-erp.pos'
])
app.run(function($rootScope) {
$rootScope.$on("$stateChangeError", console.log.bind(console));
});
app.config(function ($stateProvider, $urlRouterProvider) {
//delete $httpProvider.defaults.headers.common['X-Requested-With'];
$urlRouterProvider.otherwise('/');
$stateProvider
.state('index', {
url: '/',
templateUrl: 'views/main.html',
controller:'MainCtrl'
})
.state('comanda', {
url: '/comanda',
templateUrl: 'views/comanda.html',
controller:'ComandaCtrl'
})
.state('counter', {
url: '/counter',
templateUrl: 'views/counter.html',
controller:'CounterCtrl'
})
})
comanda.js
(function() {
'use strict';
var app;
app = angular.module('logica-erp.kds', ['timer', 'logica-erp.service.pos']);
this.ComandaCtrl = [
'$scope', '$interval', 'Ordenes', function($scope, $interval, Ordenes) {
var error, stop, success, tick;
$scope.tiempos = [
{
name: '15 seg',
value: 15000
}, {
name: '30 seg',
value: 30000
}, {
name: '60 seg',
value: 60000
}, {
name: '120 seg',
value: 120000
}
];
$scope.selected_tiempo = $scope.tiempos[1];
$scope.tipos = [
{
name: 'Alimentos',
value: 'a'
}, {
name: 'Bebidas',
value: 'b'
}, {
name: 'Todos',
value: ''
}
];
$scope.selected_tipo = $scope.tipos[2];
success = function(result) {
if (angular.toJson(result) !== angular.toJson($scope.ordenes)) {
$scope.isLoading = true;
$scope.ordenes = result;
console.log(JSON.stringify($scope.ordenes));
}
return $scope.isLoading = false;
};
error = function(error) {
console.log('error ' + error);
return $('#modal').foundation('open');
};
tick = function() {
$scope.platos = Ordenes.query({
tipo: $scope.selected_tipo.value,
sucursal: 2
});
return $scope.platos.$promise.then(success, error);
};
tick();
stop = $interval(tick, $scope.selected_tiempo.value);
$scope.change_refresh = function() {
$interval.cancel(stop);
return stop = $interval(tick, $scope.selected_tiempo.value);
};
return $scope.update_order = function(mesa, aaybb_id) {
return angular.forEach($scope.ordenes.mesas, function(orden) {
if (orden.mesa === mesa) {
return angular.forEach(orden.aaybb, function(aaybb) {
if (aaybb._id === aaybb_id) {
if (aaybb.estatus === 'ASIGNADO') {
aaybb.estatus = 'EN PROCESO';
} else if (aaybb.estatus === 'EN PROCESO') {
aaybb.estatus = 'PREPARADO';
$('#timer_' + aaybb._id)[0].stop();
}
return Ordenes.update(aaybb);
}
});
}
});
};
}
];
app.controller('ComandaCtrl', ComandaCtrl);
}).call(this);
Console log
Error: value is undefined
extractParams/<#http://127.0.0.1:9000/bower_components/angular-resource/angular-resource.js:344:11
forEach#http://127.0.0.1:9000/bower_components/angular/angular.js:336:11
extractParams#http://127.0.0.1:9000/bower_components/angular-resource/angular-resource.js:343:9
ResourceFactory/</Resource[name]#http://127.0.0.1:9000/bower_components/angular-resource/angular-resource.js:398:39
this.ComandaCtrl</tick#http://127.0.0.1:9000/scripts/controllers/comanda.js:72:25
this.ComandaCtrl<#http://127.0.0.1:9000/scripts/controllers/comanda.js:78:7
I fixed the issue, it was a old bug in the angular-resource lib. I didn't know but my bower was installing version 1.0.7 :S anyway; this was very annoying.
Related
I'm really new to Angular Unit testing using Karma and Jasmine, and I'm unable to find anything that would guide me in the right direction with regards to my problem. I have my Angular app called myApp. The app has multiple components each defined as their own modules that are then injected in the app.
App
angular.module('myApp', ['ngRoute', 'ui-bootstrap', 'dashboard', 'projects']);
Controller
angular.module('dashboard', []).controller('dashboardController',
['dashboardService', '$rootScope', '$scope', '$http', function() {
$scope.teamMemebrs = dashboardService.teamMembers;
dashboardService.getTeamMemebrs();
}]);
Service
angular.module('dashboard').service('dashboardService',
['$http', '$q', function($http, $q) {
let loadTeamMembers = () => {
return $http.get(APIendPoint).then( (response) => {
return response;
}, (response) => {
return response;
} );
};
let dashboardService = {
teamMembers : [],
getTeamMembers() {
return $q.when(loadTeamMembers()).then( (response) => {
let team = response.status === 200 ? response.data : [];
angular.copy(team, dashboardService.teamMemebrs);
});
}
};
return dashboardService;
}
]);
I am trying to test the controller and my test looks as follows, but the test fails because scope.teamMembers is undefined. What am I doing wrong?
Test Spec
describe('Dashboard', () => {
let scope, dashboardController, dashboardService, $httpBackend;
//This is what API call is expected to return
let sampleResponse = [ {name: 'Jane Doe'},
{name: 'Amy Smith'},
{name: 'John Hopkins'} ];
beforeEach(angular.mock.module('myApp'));
beforeEach(angular.mock.module('dashboard'));
beforeEach(angular.mock.inject( (_$rootScope_, _$controller_, _dashboardService_, _$httpBackend_) => {
scope = _$rootScope_.$new();
$controller = _$controller_;
dashboardService = _dashboardService_;
spyOn(dashboardService, 'getTeamMembers').and.callThrough();
dashboardController = $controller('dashboardController', { $scope: scope, dashboardService: dashboardService });
scope.$apply();
}));
it('should exist', () => {
expect(dashboardController).toBeDefined();
});
it('call dashboardService and populate scope.teamMembers', () => {
expect(dashboardService.getTeamMembers).toHaveBeenCalled();
expect(scope.teamMemebrs).toEqual(sampleResponse);
});
});
I have the following routes file in components/app/app-routes.js:
export default
function AppRoutes($stateProvider, $urlRouterProvider, $transitionsProvider) {
'ngInject';
// reference: https://ui-router.github.io/guide/ng1/migrate-to-1_0#lazy-resolves
const defaultResolvePolicy = {
when: 'EAGER'
};
const STATES = [{
name: 'logout',
url: '/logout?applicationName&desktopName&sn',
}, {
name: 'base',
url: '',
abstract: true,
template: '<ui-view></ui-view>'
}, {
name: 'app',
parent: 'base',
abstract: true,
component: 'wireApp',
data: {
authRequired: true
},
resolvePolicy: defaultResolvePolicy,
resolve: {
labels(LabelService) {
'ngInject';
return LabelService.fetch();
},
settings(SettingsService) {
'ngInject';
return SettingsService.fetch();
},
}
}, {
name: '404',
url: '/404',
parent: 'base',
template: '<w-404></w-404>',
resolvePolicy: defaultResolvePolicy,
resolve: {
module($q, $ocLazyLoad) {
'ngInject';
return $q((resolve) => {
require.ensure([], (require) => {
let mod = require('pages/404');
$ocLazyLoad.load({
name: mod.name
});
resolve(mod.name);
}, '404');
});
},
}
}, {
name: 'dashboard',
parent: 'app',
url: '/dashboard',
data: {
authRequired: true
},
views: {
'content#app': {
template: '<w-dashboard priority-tasks="$resolve.priorityTasks"></w-dashboard>'
},
},
resolvePolicy: {
module: defaultResolvePolicy,
priorityTasks: {
when: 'LAZY'
},
},
resolve: {
priorityTasks($http, $q, CacheFactory, CustomerService, RuntimeConfig, PermissionService) {
'ngInject';
if (!CacheFactory.get('priorityTasks')) {
CacheFactory.createCache('priorityTasks', {
storageMode: 'sessionStorage',
storagePrefix: 'w'
});
}
const priorityTasksCache = CacheFactory.get('priorityTasks');
if (PermissionService.check('PRIORITY_TASKS', 'view')) {
return $http.get(`${RuntimeConfig.DEV_API_URL}/customer/${CustomerService.model.currentCustomer.id}/priority-tasks`, {
cache: priorityTasksCache
}).then(({
data
}) => data, () => $q.resolve([]));
}
return [];
},
module($q, $ocLazyLoad) {
'ngInject';
return $q((resolve) => {
require.ensure([], (require) => {
let mod = require('pages/dashboard');
$ocLazyLoad.load({
name: mod.name
});
resolve(mod.name);
}, 'dashboard');
});
}
}
}, {
name: 'loans',
parent: 'app',
url: '/loans',
data: {
authRequired: true
},
views: {
'content#app': {
template: '<w-loans></w-loans>',
},
},
resolvePolicy: defaultResolvePolicy,
resolve: {
security($q, $state) {
'ngInject';
//irl get this from a service.
console.log($transitionsProvider, "TRANSISIONS PROVIDER FROM ROUTE");
// let permissions = false;
// if (!permissions) {
// return $q.reject("No permissions");
// }
},
module($q, $ocLazyLoad) {
'ngInject';
return $q((resolve) => {
require.ensure([], (require) => {
let mod = require('pages/loans');
$ocLazyLoad.load({
name: mod.name
});
resolve(mod.name);
}, 'loans');
});
}
}
}];
$urlRouterProvider
.when('', '/dashboard')
.when('/', '/dashboard')
.when('/login', '/dashboard')
.otherwise('/404');
//this will redirect all rejected promises in routes to a 404.
$transitionsProvider.onError({
to: '*',
from: '*'
}, (transition) => {
let $state = transition.router.stateService;
$state.go('404');
});
STATES.forEach((state) => {
$stateProvider.state(state);
});
}
in my loans controller (associated state above, 'loans'), however, I am unable to access the new uiCanExit callback.:
.component('wLoans', {
template: require('./loans.html'),
controller: LoansController,
bindings: {
settings: '<',
labels: '<'
}
});
function LoansController($window, $timeout, $http, $compile, $log, $filter, LoansService, ConfigService, ngDialog, SettingsService, CustomerService, ColumnRenderService, $transitions) {
'ngInject';
this.uiCanExit = function () {
console.log("WHY AM I NOT GETTING HERE");
}
}
nothing appears in the console when I switch between states, and I'm trying to figure out what to do to get the uiCanExit lifecycle hook to be run when I switch in between states (particularly dashboard and loans)
I'm not sure about this, but could the problem be caused by not referencing the component directly? Probably this only works when you reference your loans component via the component key instead of placing them in a template which renders the component. I assume that in your case the router tries to find the callback in the (not declared and thus dummy) controller instead of using the component's controller.
Please have a look at the docs: https://ui-router.github.io/docs/latest/interfaces/ng1.ng1controller.html#uicanexit
You can validate this assumption by putting a controller implementation with the uiCanExit() method in your loans state.
I am new in require.js, I am implementing requier.js with angular.js, but i got error. Here is my code:
config file:
require.config({
paths: {
angular: 'https://code.angularjs.org/1.5.5/angular.min',
angularRoute: '//rawgit.com/angular-ui/ui-router/0.2.15/release/angular-ui-router.min',
angularAnimate: '//ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-animate.min',
},
shim: {
'angular' : {'exports' : 'angular'},
'angularRoute': ['angular'],
'angularAnimate': ['angular']
},
priority: [
"angular"
],
});
require([
'angular',
'app',
'controllers/first-controller',
'controllers/second-controller',
'controllers/third-controller',
'services/services',
'directives/directives'
], function(angular, app) {
var $html = angular.element(document.getElementsByTagName('html')[0]);
angular.element().ready(function() {
// bootstrap the app manually
angular.bootstrap(document, ['WalletHubApp']);
});
}
);
This is my app file:
define(['angular'], function (angular) {
var app = angular.module('app', ['ui.router','ngAnimate']);
WalletHubApp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/walletHub/1/');
$stateProvider
.state('test', {
url: '/walletHub/:id/{folderPath:[a-zA-Z0-9/]*}',
templateUrl: function ($stateParams){
return "templates/"+$stateParams.id + '.html';
},
controllerProvider: function($stateParams) {
console.log($stateParams)
var ctrlName = $stateParams.id + "Controller";
return ctrlName;
}
});
});
return app;
});
This is Controller File:
define(['app'], function(app) {
WalletHubApp.controller('1Controller', function ($scope,$stateParams,$stateParams,$state,$http) {
$http.get('sample.json')
.then(function(res){
$scope.persons = res.data
});
var parts = $stateParams.folderPath.split('/')
$scope.params = false;
if(parts[0] != "")
{
$scope.parts = parts;
$scope.params = true;
}
})
return;
});
I dont know what is wrong in this code.Please help me to sort out this
According to official document
It is normally best to avoid coding in a name for the module and just let the optimization tool burn in the module names.
// in app.js file, remove module name :
define(["angular", "angularRoute","angularAnimate"], function(angular) {
var WalletHubApp = angular.module('WalletHubApp', ['ui.router','ngAnimate']);
WalletHubApp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/walletHub/1/');
$stateProvider
.state('test', {
url: '/walletHub/:id/{folderPath:[a-zA-Z0-9/]*}',
templateUrl: function ($stateParams){
return "templates/"+$stateParams.id + '.html';
},
controllerProvider: function($stateParams) {
console.log($stateParams)
var ctrlName = $stateParams.id + "Controller";
return ctrlName;
}
});
});
return WalletHubApp;
});
// in controller file change WalletHubApp to app
define(['app'], function(WalletHubApp) {
WalletHubApp.controller('1Controller', function ($scope,$stateParams,$stateParams,$state,$http) {
$http.get('sample.json')
.then(function(res){
$scope.persons = res.data
});
var parts = $stateParams.folderPath.split('/')
$scope.params = false;
if(parts[0] != "")
{
$scope.parts = parts;
$scope.params = true;
}
})
return;
});
So in angular it is possible to do something like this:
function userTemplateProvider($sessionStorage, $templateRequest) {
var user = $sessionStorage.user;
}
When you call the function you simply type: userTemplateProvider; and angular will automaticly inject the services.
Now im in a situation where i need to pass variables to this function.
if i do:
userTemplateProvider($sessionStorage, $templateRequest, myvar);
And ofcourse add the myvar to the function:
function userTemplateProvider($sessionStorage, $templateRequest, myvar){
var user = $sessionStorage.user;
}
Then the two services will be empty.
So my question is how do i add variables but still inject the services
My full code:
Dashboard Module
angular.module('Dashboard',[])
.config(['$stateProvider', '$urlRouterProvider', 'JQ_CONFIG', 'USER_ROLES', 'hammerDefaultOptsProvider',
function ($stateProvider, $urlRouterProvider, JQ_CONFIG, USER_ROLES, hammerDefaultOptsProvider) {
$stateProvider
.state('dashboard', {
abstract: true,
url: '/dashboard',
templateProvider: userTemplateProvider,
resolve: {
deps: ['uiLoad',
function (uiLoad) {
return uiLoad.load([
'js/controllers/headerController.js'
]);
}]
}
})
.state('dashboard.index', {
url: '/index',
templateProvider:getTemplate,
data: {
authorizedRoles: [USER_ROLES.lb, USER_ROLES.superadmin, USER_ROLES.subadmin]
},
resolve: {
deps: ['uiLoad',
function (uiLoad) {
return uiLoad.load([
'js/controllers/chart.js',
'js/controllers/dashboard/DashboardController.js',
'js/controllers/dashboard/ClientDashboardController.js'
]);
}]
}
})
}]);
TemplateLoader
angular.module('TemplateLoader', []);
function userTemplateProvider($sessionStorage, $templateRequest) {
var templateLocation = $sessionStorage.activeUser.user.user_type.super_type_id == 1 ? 'tpl/app.html' : 'tpl/client/client.html';
return $templateRequest(templateLocation);
}
function getTemplate($state, $sessionStorage) {
var templateLocation = null;
switch ($sessionStorage.activeUser.user.user_tpe.super_type_id) {
case 1:
break;
case 2:
break;
default:
break;
}
return $templateRequest(templateLocation);
}
Creating a function specialised to myvar could work, though there is probably a convention for Angular that you could use instead.
function userTemplateProvider(myvar) {
return function($sessionStorage, $templateRequest) {
var user = $sessionStorage.user;
// can also access myvar here
};
}
Then us it as:
userTemplateProvider(myvar);
I am trying to redirect users to a login page if they make an attempt to access pages that require them to be logged in. I am using Firebase and AngularJS, following this guide. The error explanation on the AngularJS site indicates that either a non-existent definition or duplicate definition is causing the issue but I cannot identify either of these in my code. Additionally, the stack trace of the error doesn't indicate which of my files caused the error, only mentioning the angular.js file.
Can anyone give me some insight as to what is causing this issue?
Note: The site runs without errors and users can log in and out if I leave out the resolve section of the $routeProvider.
Here is my app.js
angular.module('richWebApp', ['ngRoute', 'firebase', 'objectFilter'])
.constant('fb', {
url: 'https://<my-firebase-app>.firebaseio.com/' //name removed for security reasons
})
.run(function($rootScope, $location) {
$rootScope.$on("$routeChangeError", function(event, next, previous, error) {
if(error === "AUTH_REQUIRED") {
$location.path("/login");
}
});
})
.config(function($routeProvider){
$routeProvider.
when('/login', {
templateUrl: 'pages/login/login.html'
}).
when('/main', {
templateUrl: 'pages/main/main.html',
resolve: {
"currentAuth": ["Auth", function(Auth) {
return Auth.$requireAuth();
}]
}
}).
when('/thread/:threadId', {
templateUrl: 'pages/thread/thread.html',
resolve: {
"currentAuth": ["Auth", function(Auth) {
return Auth.$requireAuth();
}]
}
}).
otherwise({
redirectTo: '/login'
});
});
Here is the main.js controller
angular.module('richWebApp')
.controller('mainPageController', function($scope, $location, userService, currentAuth, threadService, fb, $firebaseAuth, $filter){
$scope.user = userService.getLoggedInUser();
$scope.newThreadTitle = '';
$scope.threadSubject = ''
$scope.createNewThread = false;
$scope.sortBy = 'dateAdded'
$scope.threads = threadService.getAllThreads();
$scope.getSubjects = function(subject) {
return $scope.threads.subject;
}
$scope.beginAddThread = function() {
$scope.createNewThread = true;
}
$scope.addThread = function(){
if(!$scope.newThreadTitle || !$scope.newThreadSubject){
return false;
}
var date = new Date();
var newThread = {
title: $scope.newThreadTitle,
subject: $scope.newThreadSubject,
username: $scope.user.name,
numComments: 0,
comments: [],
dateAdded: date.getTime()
};
$scope.threads.$add(newThread);
$scope.newThread = '';
$scope.newThreadTitle = '';
$scope.newThreadSubject = '';
$scope.createNewThread = false;
}
$scope.sortByDate = function() {
$scope.sortBy = 'dateAdded';
}
$scope.sortByPopularity = function() {
$scope.sortBy = 'numComments';
}
$scope.searchSubject = function(subject) {
$scope.searchThread = subject;
}
$scope.logout = function(){
userService.logout();
}
});
Here is the thread.js controller
angular.module('richWebApp')
.controller('threadPageController', function($scope, $location, $routeParams, $filter, currentAuth, threadService, fb, userService){
var threadId = $routeParams.threadId;
$scope.newComment = '';
var thread = threadService.getThread(threadId);
thread.$bindTo($scope, 'thread')
$scope.addComment= function(){
if(!$scope.newComment){
return false;
}
var currentUser = userService.getLoggedInUser();
var date = new Date();
var newComment = {
text: $scope.newComment,
username: currentUser.name,
dateAdded: date.getTime(),
userPic: currentUser.profilePic
};
$scope.thread.comments = $scope.thread.comments || [];
$scope.thread.comments.push(newComment);
$scope.thread.numComments += 1;
$scope.newComment = '';
}
});
Your code is referring to an Auth factory, which is shown in the example under Retrieving Authentication State. Include this in your code.
.factory("Auth", ["$firebaseAuth",
function($firebaseAuth) {
var ref = new Firebase("<YOUR FIREBASE>");
return $firebaseAuth(ref);
}
]);