AngularJS Unknown Provider Error Message - javascript

I have an angular app that will not load and is returning the error message:
Error: [$injector:unpr] Unknown provider: navigatorProvider <-
navigator <- LayoutController
This is ever since I introduced a service I have this registered on the controller, but it still not working. The controller referenced is:
(function () {
"use strict";
angular.module("HtJobPortal").controller("LayoutController",LayoutController);
LayoutController.$inject = ["$scope", "navigator"];
function LayoutController($scope, navigator){
var layout = this;
// Layout
layout.loadTemplate = function() {
return navigator.loadTemplate();
}
// Initialise pending and set roles
layout.init = function () {
// Global Start up
};
layout.init();
}
})();
This is the service:
(function() {
var navigator = angular.module('navigator', []);
navigator.factory('loadTemplate', function () {
var loadTemplate = this;
// Page Directory
navigator.login = "templates/login.html";
navigator.dashboard = "templates/dashboard.html";
navigator.job = "templates/job.html";
// Template switcher
navigator.loadTemplate = function () {
return navigator.login;
}
return loadTemplate;
});
}());
And the app page just in case I've missed something there:
(function () {
'use strict';
angular.module('HtJobPortal', []);
})();

You are add the dependencies when defining the HtJobPortal module
//define dependencies
angular.module('HtJobPortal', ['navigator']);
In the controller, you need to inject the factory in controller
(function () {
"use strict";
angular.module("HtJobPortal").controller("LayoutController",LayoutController);
LayoutController.$inject = ["$scope", "loadTemplate"];
function LayoutController($scope, loadTemplate){
var layout = this;
// Layout
layout.loadTemplate = function() {
return loadTemplate.loadTemplate();
}
// Initialise pending and set roles
layout.init = function () {
// Global Start up
};
layout.init();
}
})();
And define factory as
(function () {
angular.module('navigator', []).factory('loadTemplate', function () {
// Page Directory
var login = "templates/login.html";
var dashboard = "templates/dashboard.html";
var job = "templates/job.html";
return {
// Template switcher
loadTemplate: function () {
return login;
}
};
});
})();

To create a factory\service\controllers , you generally don't require a new module every time. It's preferred to declare one module and register your controller\factory\services to same.
In your case, you can do it like:
(function() {
angular.module('HtJobPortal', [..define other module dependency here..]);
angular.module('HtJobPortal')
.factory('loadTemplate', function () {
var loadTemplate = {};
// Page Directory
loadTemplate.login = "templates/login.html";
loadTemplate.dashboard = "templates/dashboard.html";
loadTemplate.job = "templates/job.html";
// Template switcher
loadTemplate.loadTemplate = function () {
return loadTemplate .login;
}
return loadTemplate; // return object from factory
})
.controller("LayoutController",LayoutController);
LayoutController.$inject = ["$scope", "loadTemplate"]; //inject factory
function LayoutController($scope, loadTemplate){
var layout = this;
// Layout
layout.loadTemplate = function() {
return loadTemplate.loadTemplate(); // call factory method
}
// Initialise pending and set roles
layout.init = function () {
// Global Start up
};
layout.init();
};
}());

Related

how to call angular scope function from javascript function inside controller

I have angular controller and Javascript function in that function , i am calling angular function. I am getting error: $scope.Name is not a function, $scope.dates is not a function.
function validation() {
$scope.pageload = true;
$scope.Name();
$scope.dates();
}
$scope.Name = function () {
// do something
}
$scope.dates = function () {
// do something
}
working fine inside the controller
var MyController = function ($scope, service)
{
function validation() {
$scope.pageload = true;
$scope.Name();
$scope.dates();
}
$scope.Name = function () {
// do something
}
$scope.dates = function () {
// do something
}
});
working:
var MyController = function ($scope, service)
{
LoginHomeService.getHomeService(function (data) {
$rootScope.CT1SessionObj = data.CT1SessionObj;
validation();
}, function (response) {
alert(response.Message);
});
function validation() {
$scope.pageload = true;
$scope.Name();
$scope.dates();
}
$scope.Name = function () {
// do something
}
$scope.dates = function () {
// do something
});
Not working:
var MyController = function ($scope, service)
{
LoginHomeService.getHomeService(function (data) {
$rootScope.CT1SessionObj = data.CT1SessionObj;
validation();
function validation() {
$scope.pageload = true;
$scope.Name();
$scope.dates();
}
$scope.Name = function () {
// do something
}
$scope.dates = function () {
// do something
}
}, function (response) {
alert(response.Message);
});
});
Declare $scope.Name and $scope.dates on top of validation()
Javascript works from top to bottom, so your functions $scope.Name and $scope.Dates do not exist 'yet'.
Also, try not to use 'Name' as a function. Most of these words are reserved keywords.
var myApp = angular.module('myApp', []);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
$scope.Name = function() {
// do something
}
$scope.dates = function() {
// do something
}
function validation() {
$scope.pageload = true;
$scope.Name();
$scope.dates();
}
}
Fiddle: http://jsfiddle.net/Lvc0u55v/4872/
An even better approach would be the 'John Papa style' : Y033
Place bindable members at the top of the controller, alphabetized, and not spread through the controller code.
Why?: Placing bindable members at the top makes it easy to read and
helps you instantly identify which members of the controller can be
bound and used in the View.
Why?: Setting anonymous functions in-line can be easy, but when those
functions are more than 1 line of code they can reduce the
readability. Defining the functions below the bindable members (the
functions will be hoisted) moves the implementation details down,
keeps the bindable members up top, and makes it easier to read.
/* avoid */
function SessionsController() {
var vm = this;
vm.gotoSession = function() {
/* ... */
};
vm.refresh = function() {
/* ... */
};
vm.search = function() {
/* ... */
};
vm.sessions = [];
vm.title = 'Sessions';
}
/* recommended */
function SessionsController() {
var vm = this;
vm.gotoSession = gotoSession;
vm.refresh = refresh;
vm.search = search;
vm.sessions = [];
vm.title = 'Sessions';
////////////
function gotoSession() {
/* */
}
function refresh() {
/* */
}
function search() {
/* */
}
}
As #Harald Wiesinger mentioned declare called functions prior to calling function.
Put validation after the scope functions
$scope.Name = function () {
// do something
}
$scope.dates = function () {
// do something
}
function validation() {
$scope.pageload = true;
$scope.Name();
$scope.dates();
}

How can I inject Modules in Javascript?

I'm using Module pattern, now I wanted to know is that possible to inject one module into another like AngularJs.
Below is sample code that I've tried.
module.js
var AnotherModule = (function () {
function AnotherModule() {
this.anotherFunction = function () {
alert('Inside another Module');
}
}
return AnotherModule;
})(window);
var AnotherModule = new AnotherModule();
var Module = (function (window, AnotherModule) {
function Module(AnotherModule) {
var privateMethod = function() {
}
this.getName = function (brand) {
console.log('Inside get Name');
console.log(AnotherModule);
}
}
return Module;
})(window, AnotherModule);
var module = new Module();
module.getName();

Unit testing Angular controller using capture variable for 'this' with controllerAs syntax

I've been following this Angular style guide by John Pappa, and I've been having problems testing with the controllerAs syntax. Specifically the guide says to use a capture variable like so var vm = this; to avoid attaching things to $scope inside the controller.
My issue comes when I start to test controllers using this capture variable. When I create a controller in my unit test, I am not able to call methods attached to the capture variable.
My code is as follows:
Controller:
(function(){
'use strict';
/**
* #ngdoc function
* #name mytodoApp.controller:MainCtrl
* #description
* # MainCtrl
* Controller of the mytodoApp
*/
angular.module('mytodoApp')
.controller('MainCtrl', function ($scope) {
/* jshint validthis: true */
var vm = this;
vm.tasks = [];
vm.addTask = addTask;
vm.removeTask = removeTask;
function addTask() {
if(!contains(vm.tasks, $scope.task)){
vm.tasks.push($scope.task);
} else {
vm.isInvalid = true;
}
$scope.task = '';
};
function removeTask(index) {
vm.tasks.splice(index, 1);
};
var contains = function(list, item) {
var res = list.indexOf(item);
return res === -1 ? false : true;
};
});
})();
Unit Test:
'use strict';
describe('Controller: MainCtrl', function () {
// load the controller's module
beforeEach(module('mytodoApp'));
var MainCtrl,
scope;
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
MainCtrl = $controller('MainCtrl', {
$scope: scope
// place here mocked dependencies
});
}));
it('should attach a list of tasks to the viewmodel', function () {
expect(MainCtrl.tasks.length).toBe(0);
});
it('should add items to the list', function() {
scope.task = 'example task';
MainCtrl.addTodo();
expect(MainCtrl.tasks.length).toBe(1);
});
});
I am getting this error:
PhantomJS 1.9.8 (Mac OS X 0.0.0) Controller: MainCtrl should add items to the list FAILED
TypeError: 'undefined' is not a function (evaluating 'MainCtrl.addTodo()')
at /Users/kyle/Code/AngularProjects/mytodo/test/spec/controllers/main.js:28
There is no addTodo() function in your MainCtrl. Did you mean to run addTask()?

Is there anyway to define an undefined object in Visual Studio intellisense?

Lets say I have a controller in AngularJS:
myApp.controller('SearchController',
function ($scope, UserService) {
// for intellisense, UserService is undefined here
var user = UserService.getUsers().then(function(data){
// yada yada
}, function(err){
// yada yada
});
});
However, in my intellisense file, I can dynamically inject UserService to get its functions like this:
intellisense.addEventListener('statementcompletion', function (event) {
// tried doing this, but doesn't work!
// event.target = {};
var injector = angular.injector(['ng', 'myApp']);
var dependency = injector.get(event.targetName);
event.items = [];
for (method in dependency) {
intellisense.logMessage(method);
event.items.push({ name: method, kind: 'field', value: function () { } });
}
});
Now, if I have a global variable (or function variable) defined as UserService = {} and inside my controller function I type UserService. I will get a pop up of all the functions in the service. But if I don't have it defined, since it is interpreted as undefined by intellisense, it can't show me the options even though statementcompletion is working (as seen in the Javascript Language Service console).
My question is, apart from annotating the function, is there anyway to define UserService as an object in the intellisense file? Defining event.target = {} does not work (see intellisense code above).
One way that works is to "call" the component functions (controller, services, etc) from intellisense code with empty objects.
I am sure this can be a lot cleaner but here's what I've done:
https://github.com/diwasbhattarai/angularjs-intellisense
By John Bledsoe: https://github.com/jmbledsoe/angularjs-visualstudio-intellisense/
references.js - add this file as reference in Tools>Options>TextEditor>Javascript>Intellisense>References
/// <reference path="../source/lib/assetBundle.js" />
/// <reference path="_moduleDecorator.js" />
/// <reference path="_componentDecorator.js" />
/// <reference path="../source/app/appBundle.js" />
intellisense.addEventListener('statementcompletion', function (event) {
// for core angular objects
addComponentToIntellisense('ng');
// for custom objects in application modules
for (var moduleIndex in modules) {
addComponentToIntellisense(modules[moduleIndex]);
}
function addComponentToIntellisense(module) {
var $injector = angular.injector(['ng', module]),
dependency = $injector.get(event.targetName),
dep;
if (typeof dependency === "function") dep = new dependency();
else dep = dependency;
for (var method in dep) {
event.items.push({ name: method, kind: 'field', value: dependency[method] });
}
}
});
_moduleDecorator.js - to keep track of all the modules in your app
//_moduleDecorator
(function () {
var originalModule = angular.module;
// TODO change to array
modules = {};
var rep = false;
var count = 0;
angular.module = function () {
for (var k in modules) {
if (modules[k] === arguments[0]) {
rep = true;
break;
}
}
if (!rep) modules[count++] = arguments[0];
return originalModule.apply(angular, arguments);
};
})();
_componentDecorator.js - to "call" component functions with empty object parameter
(function () {
// pick all the components in all modules and initialize them for intellisense
for (var moduleIndex in modules) {
var currentModule = angular.module(modules[moduleIndex]),
queue = currentModule._invokeQueue,
// add other components such as value, provider, etc later
angularComponents = ['controller', 'factory', 'service', 'value'];
for (var i = 0; i < angularComponents.length; i++) {
var currentComponent = angularComponents[i],
originalComponentFn = currentModule[currentComponent];
currentModule[currentComponent] = (function (currentModule, queue, originalComponentFn) {
return function () {
originalComponentFn.apply(currentModule, arguments);
initializeComponents(queue);
};
})(currentModule, queue, originalComponentFn);
}
}
function initializeComponents(queue) {
var elem = queue.filter(function (element) {
var componentName = element[2][0].toLowerCase();
return (componentName.indexOf(componentName) !== -1);
});
for (var i = 0; i < elem.length; i++) {
var tempComp = elem[i][2][1],
compFunc;
// for array notation for DI
if (typeof tempComp !== "function") {
compFunc = tempComp[tempComp.length - 1];
} else {
compFunc = tempComp;
}
// 10 parameter dependencies initialization for now
compFunc({}, {}, {}, {}, {}, {}, {}, {}, {}, {});
}
}
})();

Typescript generating redundant variable

Consider the following Typescript code:
module demoAppModule{
'use strict';
export module nest{
export var hello = function () {
alert('Hello!');
};
}
}
demoAppModule.nest.hello();
After transpiling we have the following javascript code:
var demoAppModule;
(function (demoAppModule) {
'use strict';
(function (nest) {
nest.hello = function () {
alert('Hello!');
};
})(demoAppModule.nest || (demoAppModule.nest = {}));
var nest = demoAppModule.nest;
})(demoAppModule || (demoAppModule = {}));
demoAppModule.nest.hello();
Why is this line generated? It hurts my eyes.
var nest = demoAppModule.nest;
Short Answer: Its needed to access the module variable locally. E.g.
module demoAppModule{
'use strict';
export module nest{
export var hello = function () {
alert('Hello!');
};
}
// The following would not be possible without that line
console.log(nest.hello);
}
demoAppModule.nest.hello();
Longer Answer: Its similar to the var added before a module e.g. notice var x:
// TypeScript
module x{export var foo;}
// Generated JavaScript
var x;
(function (x) {
x.foo;
})(x || (x = {}));
But when you are inside a module + export a module the var needs to be added to outermodule.innermodule so you do not do var innermodule upfront. You add it to outermodule and then create a local variable to point to the innermodule which you can see in the generated javascript:
// Notice var here
var demoAppModule;
(function (demoAppModule) {
'use strict';
// Notice no var here
(function (nest) {
nest.hello = function () {
alert('Hello!');
};
})(demoAppModule.nest || (demoAppModule.nest = {}));
// Notice var assinged afterwards
var nest = demoAppModule.nest;
// The following would not be possible without that line
console.log(nest.hello);
})(demoAppModule || (demoAppModule = {}));
demoAppModule.nest.hello();

Categories

Resources