for a variety of reasons, my company decided to follow this model for our various objects in Angular
(function(angular) {
'use strict';
function Principal($q, $http, $cookies) {
this.$q = $q;
this.$http = $http;
this.$cookies = $cookies;
}
Principal.prototype.isIdentityResolved = function() {
return angular.isDefined(this._identity);
};
}());
The module is being defined by a master one level above this.
var Principal = require('./Principal');
var AuthServ = require('./AuthorizationService');
var SecAng = angular.module('SecAng', []);
SecAng.service('principal', Principal);
SecAng.service('authorization', AuthServ);
module.exports = SecAng;
and then browsify resolves that to a name and its included in my module in my app.js
My problem is the line return angular.isDefined(this._identity);. I keep getting errors saying that angular is undefined. Any ideas why this would be happening?
Pass angular into your self-invoking function:
(function(angular) {
'use strict';
...
}(angular));
Related
I know it is a bad practice to use this syntax to register controllers in angular:
var app = angular.module('app',[]);
app.controller('mainController',function(){
// code
});
because of global variables issue so it's recommended to use the getter syntax in angular:
angular.module('app',[]);
angular.module('app').controller('mainController',function(){
//code
};
but every time I have to write the name of my application to get it so I think in another solution to do that:
'use strict';
const _APP_ = (function(){
var appName = 'app';
var result = {
init: function(dependencies){
document.body.setAttribute('ng-app',appName);
if(!dependencies || !Array.isArray(dependencies)){
dependencies = [];
}
angular.module(appName,dependencies);
},
$: function(){
return angular.module(appName);
}
};
return Object.freeze(result);
})();
now app.js file just has:
'use strict';
(function(){
_APP_.init();
})();
and to create a new controller:
'use strict';
(function(){
_APP_.$().controller('mainController',ctrl);
function ctrl(){
// code
}
})();
I'm always interested in the best practices so I need your feedback about my solution or if there is a better.
As stated in the title, I'm trying to pass a value (ID) from one controller (PerksApprovalController) going to another controller (PerksDetailsController). Please find below image for visual reference.
What I want to do is, when I click the "Show Details" button, it will redirect me to another page to display the details of the Control Number that I pass.
Below is my implementation.
Show Details Button Code
<button class="btn btn-xs" ng-click="vm.showDetails(p.ControlNumber)">Show Details</button>
PerksApprovalCtrl.js
(function () {
'use strict';
var app = angular.module('app');
PerksApprovalController.$inject = ['$window', 'app.perksService', 'app.sharedValuesFactory'];
app.controller('app.perksApprovalController', PerksApprovalController);
function PerksApprovalController($window, PerksService, SharedValuesFactory) {
/* jshint validthis:true */
var vm = this;
vm.showDetails = function (controlNo) {
SharedValuesFactory.setControlNo(controlNo);
$window.location = '/PerksDetails/PerksView';
}
}
})();
PerksDetailCtrl.js
(function () {
'use strict';
var app = angular.module('app');
PerksDetailController.$inject = ['$scope', '$http', '$q', '$window', 'app.perksService', 'app.sharedValuesFactory'];
app.controller('app.perksDetailController', PerksDetailController);
function PerksDetailController($scope, $http, $q, $window, PerksService, SharedValuesFactory) {
var vm = this;
PerksService.getPerksItems(SharedValuesFactory.getControlNo()).then(function (response) {
vm.perksItemDetails = response.data;
});
}
})();
I have created a service just like what they suggested in some topics here.
sharedValuesFactory.js
(function () {
'use strict';
var app = angular.module('app');
// SharedValuesFactory.$inject = ['$http'];
app.factory('app.sharedValuesFactory', SharedValuesFactory);
function SharedValuesFactory() {
var controlNoShared;
return {
setControlNo: function (c) {
this.controlNoShared = c;
},
getControlNo: function () {
return this.controlNoShared;
}
}
}
})();
My problem now is, everytime the details page is loaded, SharedValuesFactory.getControlNo() returns undefined. Looks like SharedValuesFactory is reset after the redirect or page load.
Any idea on how to properly pass a value from one controller to another?
TIA
I have a specific way of passing value in between Controllers. Hope it does the trick!
Note:
Not Sure what sharedValuesFactory.js is being used for! Assumming You are using this service to pass Data in between Controllers only. According to me only One service suites your requirement i.e PerksService.
The button passes the value (ID) of "ControlNumber".
<button class="btn btn-xs" ng-click="vm.showDetails(p.ControlNumber)">Show Details</button>
In PerksApprovalCtrl.js pass the controlNo you are getting on button click to the url of the page as in of a different view
PerksApprovalCtrl.js
(function () {
'use strict';
var app = angular.module('app');
PerksApprovalController.$inject = ['$window', 'app.perksService'];
app.controller('app.perksApprovalController', PerksApprovalController);
function PerksApprovalController($window, PerksService) {
/* jshint validthis:true */
var vm = this;
vm.showDetails = function (controlNo) {
$window.location = ;
$location.path('/PerksDetails/PerksView'+controlNo);
}
}
})();
In Routes.js or the place where you define the routes of your angular application add the following lines:
.when('/PerksDetails/PerksView/:controlNo', {
templateUrl: '<YOU DEFINE THE TEMPLATE>',
controller: 'PerksDetailController',
reloadOnSearch: false })
Here ":controlNo" is used to pass the value you are passing in the url from PerksApprovalController.
In PerksDetailController we get the controlNo from routeParams and pass it to your PerksService to get the details from it.
PerksDetailCtrl.js
(function () {
'use strict';
var app = angular.module('app');
PerksDetailController.$inject = ['$scope', '$http', '$q', '$window', '$routeParams', 'app.perksService'];
app.controller('app.perksDetailController', PerksDetailController);
function PerksDetailController($scope, $http, $q, $window, $routeParams, PerksService) {
var vm = this;
PerksService.getPerksItems($routeParams.controlNo).then(function (response) {
vm.perksItemDetails = response.data;
});
}
})();
Hope it Solves your problem! Thank You!
I want use unit test in angular, but the webapp that I working on it is created on its owe structure. for example :
(function() {
'use strict';
angular
.module('app', [
'ngAnimate',
'ui.load',
'ui.jp',
'oc.lazyLoad'
]);})();
And one of its controllers :
(function() {
'use strict';
angular
.module('app')
.controller('EditorCtrl', EditorCtrl);
function EditorCtrl($scope) {
var vm = $scope;
vm.options = {
toolbar: [
['style', ['bold', 'italic', 'underline', 'clear']],
]
};
}})();
And I have no idea how to use unit test to this app because my test cant find controller.
This is my controller and test :
(function () {
'use strict';
angular
.module('app')
.controller('DashboardCtrl', dashboard);
describe('test dashboard', function () {
beforeEach(module('DashboardCtrl'));
var $controller;
beforeEach(inject(function (_$controller_) {
$controller = _$controller_;
}));
describe('sum', function () {
it('1 + 1 should equal 2', function () {
var $scope = {};
var controller = $controller('DashboardCtrl', {$scope: $scope});
$scope.x = 1;
$scope.y = 2;
$scope.sum();
expect($scope.z).toBe(3);
});
it('z should default to zero', function () {
var $scope = {};
var controller = $controller('DashboardCtrl', {$scope: $scope});
expect($scope.z).toBe(0);
});
});
});
function dashboard($scope) {
$scope.name = 'Dashboard';
$scope.z = 0;
$scope.sum = function () {
$scope.z = $scope.x + $scope.y;
};
}
})();
And in karma test show me this error :
Error: [$injector:modulerr] Failed to instantiate module DashboardCtrl due to:
Error: [$injector:nomod] Module 'DashboardCtrl' 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.
That indicate that cant find "DashboardCtrl" controller.
the problem solved by add all modules in files options of karma.conf.js
the point is event lake of one of modules that are injected is main module that here is app stop your test, so addition to include your controller you need to add all module are mentioned.
When unit testing use $controller for getting a handle on a controller instance https://docs.angularjs.org/api/ng/service/$controller like var ctrlToTest = $controller('EditorCtrl')(newTestScope); To create a new test scope you can use var newTestScope = $rootScope.$new()
I have two modules and factories in both, and I need to implement factory from the first module into another module.
angular.module('APIs', [])
.value ("myValue" , "12345")
.factory('apiUrl',['config','url',apiUrl])
function apiUrl(config,url){
}
angular.module('users.service', ['APIs'])
.factory('userService',['myValue',userService])
function userService(apiUrl,myValue){
//login function
function login(){
console.log('myValue',myValue)
console.log('loginUrl',apiUrl)
}
return {
login:login
}
}
notice: no problem when I inject myValue, but the problem in APIs Factory
and my log:
Error: [$injector:unpr] http://errors.angularjs.org/1.5.0/$injector/unpr?p0=urlProvider%20%3C-%20url%20%3C-%20apiUrl%20%3C-%20userService
at Error (native)
and sorry for my English.
I would do it like this:
If you create factory use angular.module('app').factory(). If you create service use angular.module('app').service()
Always try to have same module name. It is easier later, when you have big application, because of dependency injection.
Try to keep files separately, and concatenate it later, for example using gulp gulp-concat
Try to keep all you configuration in app.js file and, when you concatenating file, remember, this file should be on top.
I would keep values and constants in app.js file or would create new file like factory or service and include it, same as I injected it below.
app.js
(function () {
'use strict';
var app = angular.module('app', [
// other module
]);
app.value('myValue', '12345');
app.constant('myConst', 'some_constant');
app.config(['$interpolateProvider', function ($interpolateProvider) {
$interpolateProvider.startSymbol('[[');
$interpolateProvider.endSymbol(']]');
}]);
}());
factory.js
(function () {
'use strict';
angular
.module('app')
.factory('apiUrlFactory', apiUrlFactory);
apiUrlFactory.$inject = [];
function apiUrlFactory() {
var self = this;
self.url = 'some_url';
return self;
}
}());
service.js
(function () {
'use strict';
angular
.module('app')
.service('userService', userService);
userService.$inject = ['apiUrlFactory', 'myValue'];
function userService(apiUrlFactory, myValue) {
var self = this;
self.login = function () {
console.log('myValue', myValue);
console.log('loginUrl', apiUrlFactory.url);
};
return self;
}
}());
If you have more questions, do not hesitate to contact with me. Also try angular style guide https://github.com/johnpapa/angular-styleguide It will help you a lot.
I wonder if someone could assist me in figuring out how to wire up my new angular service module.
I keep getting the same Javascript error :
Error: [$injector] Unknown provider: gridHierarchyServiceProvider" <-- gridHierarchyService
My new services/gridHierarchyService.js file :
(function () {
'use strict';
var controllerId = 'gridHierarchyService';
angular.module('app').controller(controllerId, ['common', gridHierarchyService]);
function gridHierarchyService(common) {
var service = {
getDataSourceSchema: getDataSourceSchema
};
return service;
function getDataSourceSchema() {
var i = 1;
// TESTING...
}
}
});
and in my dashboard.js file, I attempt to inject this new service module:
(function () {
'use strict';
var controllerId = 'dashboard';
angular.module('app').controller(controllerId, ['common', 'datacontext', 'gridHierarchyService', dashboard]);
function dashboard(common, datacontext, gridHierarchyService) {
...
}
and of course I'm loading it up in my index.html:
<!-- app Services -->
<script src="app/services/datacontext.js"></script>
<script src="app/services/gridHierarchyService.js"></script>
<script src="app/services/directives.js"></script>
However, I'm clearing missing something here.
I also tried mimicking my datacontext.js service, using the .factory() call:
angular.module('app').factory(serviceI,d [...]);
but it doesn't work.
========== UPDATE !!! ============
I'm happy to say it was a very easy fix, and thanks to the community here !
WORKING SERVICE :
(function () {
'use strict';
var serviceId = 'gridHierarchyService';
angular.module('app').factory(serviceId, ['common', gridHierarchyService]);
function gridHierarchyService(common) {
var service = {
getDataSourceSchema: getDataSourceSchema
};
return service;
function getDataSourceSchema() {
var i = 1;
i = 2;
}
}
})();
I see that you are defining your controllers inside anonymous functions but that you never execute those anonymous functions.
Your code:
(function(){
//declarations
alert('You will never see me because I do not execute');
});
Fixed code (notice the parens at the end):
(function(){
//declarations
alert('You can see me!');
})();
See the above code run here: http://jsfiddle.net/wilsonjonash/cDBc7/
See more about the module pattern here:
http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html
Also, you were right to try factory for a service. To make your gridHierarchyService into a service (rather than a controller), just change controller to factory or service in
var controllerId = 'gridHierarchyService';
angular.module('app').controller(controllerId, ['common', gridHierarchyService]);
Hope that does the trick for you.