I have an Angular framework I am building that I am trying to make router agnostic, I would like to be able to use any router. So far I have tested it with ng router and it works fine, but when I try to use UI-Router I am getting the injector error. I am not sure if I have placed it in the wrong module, or if it a deeper issue. The framework broadcasts a route or a state, depending on how I set up the Framework directive. I have injected UI-Router into my main module and injected $stateProvider into my controller that needs to use it. I am stumped. Any help would be greatly appreciated.
Here is main module:
(function () {
"use strict";
angular.module("app", ["ptFramework", "ui.router", "ngStorage", "ui.bootstrap"]);
})();
Here is framework module:
(function () {
"use strict";
angular.module("ptFramework", [,"ptMenu", "ptDashboard"]);
})();
Here is framework controller:
(function () {
"use strict";
angular.module("ptFramework").controller("ptFrameworkController",
['$scope', '$window', '$timeout', '$rootScope', '$stateProvider',
function ($scope, $window, $timeout, $rootScope, $stateProvider) {
$scope.isMenuVisible = true;
$scope.isMenuButtonVisible = true;
$scope.isMenuVertical = true;
$scope.$on('pt-menu-item-selected-event', function (evt, data) {
$scope.stateString = data.state;
$stateProvider.go(data.state);
checkWidth();
broadcastMenuState();
});
$scope.$on('pt-menu-orientation-changed-event', function (evt, data) {
$scope.isMenuVertical = data.isMenuVertical;
$timeout(function () {
$($window).trigger('resize');
}, 0);
});
$($window).on('resize.ptFramework', function () {
$scope.$apply(function () {
checkWidth();
broadcastMenuState();
});
});
$scope.$on("$destroy", function () {
$($window).off("resize.ptFramework"); // remove the handler added earlier
});
var checkWidth = function () {
var width = Math.max($($window).width(), $window.innerWidth);
$scope.isMenuVisible = (width >= 768);
$scope.isMenuButtonVisible = !$scope.isMenuVisible;
};
$scope.menuButtonClicked = function () {
$scope.isMenuVisible = !$scope.isMenuVisible;
broadcastMenuState();
};
var broadcastMenuState = function () {
$rootScope.$broadcast('pt-menu-show',
{
show: $scope.isMenuVisible,
isVertical: $scope.isMenuVertical,
allowHorizontalToggle: !$scope.isMenuButtonVisible
});
};
$timeout(function () {
checkWidth();
}, 0);
}
]);
})();
As you can see I have injected $stateProvider in both the minsafe array and the function. I dont understand why I am getting this error
Here is the rote.config where I use it:
"use strict";
angular.module('app').config([
'$stateProvider', function ($stateProvider) {
$stateProvider
.state('dashboard',
{
url: "/dashboard",
template: "<h1>dashboard</h1>"
});
Any input would be greatly appreciated.
Thanks,
John.
In the controller:
$stateProvider.go(data.state);
should be
$state.go(data.state);
As a consequence, inject $state instead of $stateProvider.
Related
I am using requireJS for my angularjs app.
common.service.js
define(function () {
var coreModule = angular.module('coreModule');
coreModule.config(['$provide', function ($provide) {
$provide.factory("CommonService", CommonService);
}]);
CommonService.$inject = ["$http", "$q", "$window"];
function CommonService($http, $q, $window) {
var service = {};
service.sharedValue;
return service;
}
});
page1.controller.js
define(function () {
var coreModule = angular.module('coreModule');
coreModule.controller('Page1Controller', ['$scope', "CommonService", function ($scope, CommonService) {
// Q2: common service
$scope.commonService = CommonService;
}]);
});
Now When I am running my app, it throws me below error:
Error: [$injector:unpr] Unknown provider: CommonServiceProvider <- CommonService <- Page1Controller
any inputs?
Your core module should have empty dependencies injected
var coreModule = angular.module('coreModule',[]);
Also in page1. controller you dont have to declare the module again, you can just use
angular.module('coreModule')
.controller('Page1Controller', ['$scope', "CommonService", function ($scope, CommonService) {
Define config
Define the service
Define the controller, inject the service, use the dependency in function declaration etc. As you would know, both are needed, after all you need the those handles, else what's the point in injecting.
Define a module, define module dependencies. NOTE that the service has to be defined before controller. If you reverse the order, you will get an error, probably that's what is happening here. Without full code, I can't tell.
bootstrap angular.
Finally working plunkr: http://plnkr.co/edit/CE9enkgW3KASx8pf5vdb?p=preview
define('config',[],function(){
function config($routeProvider) {
$routeProvider.when('/home', {templateUrl: 'tpl.home.html', controller: 'HomeController'})
.otherwise({redirectTo: '/home'});
}
config.$inject=['$routeProvider'];
return config;
});
define('dataSvc',[], function(app){
function factoryFunc ($q, $timeout){
var svc = {getData: getData};
return svc;
function getData() {
console.log('executing function');
var d = $q.defer();
$timeout(function(){
console.log("firing timeout");
d.resolve({name:"test", data:[1, 2, 3, 4]});
}, 750);
return d.promise;
}
}
factoryFunc.$inject=['$q', '$timeout'];
return factoryFunc;
});
define('HomeController',[], function() {
function HomeController($scope, dataSvc) {
$scope.name = "Mahesh";
dataSvc.getData().then(function(result){
$scope.data=result;
console.log($scope.data);
});
}
HomeController.$inject=['$scope','dataSvc'];
return HomeController;
});
define('coreModule', ['config', 'dataSvc', 'HomeController']
, function(config, dataSvc, HomeController){
var app = angular.module('app', ['ngRoute','ngResource']);
app.config(config);
app.factory('dataSvc',dataSvc);
app.controller('HomeController', HomeController);
});
require(['coreModule'],
function() {
angular.bootstrap(document, ['app']);
}
);
Refer also,
https://www.sitepoint.com/using-requirejs-angularjs-applications/
http://beletsky.net/2013/11/using-angular-dot-js-with-require-dot-js.html
I am able to lazy load angularjs with the help of requirejs. But, how can I load modules that needs to be associated to the controller?
My example configuration in app.js looks like the following, loading all the providers and keeping a reference.
var app = angular.module('myApp', ['ui.router'])
var cacheProviders = {};
app.getProvider = function () {
return cacheProviders.$provide;
}
app.getCompileProvider = function () {
return cacheProviders.$compileProvider;
}
app.getControllerProvider = function () {
return cacheProviders.$controllerProvider;
}
app.getFilterProvider = function () {
return cacheProviders.$filterProvider;
}
app.config(['$stateProvider', '$urlRouterProvider', '$controllerProvider', '$compileProvider', '$filterProvider', '$provide',
function ($stateProvider, $urlRouterProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {
(function () {
cacheProviders.$controllerProvider = $controllerProvider;
cacheProviders.$compileProvider = $compileProvider;
cacheProviders.$filterProvider = $filterProvider;
cacheProviders.$provide = $provide;
})();
var lazyCtrlLoad = function (controllerName) {
return ["$q", function ($q) {
var deferred = $q.defer();
require([controllerName], function () {
deferred.resolve();
});
return deferred.promise;
}];
}
$stateProvider.state('main.view2b', {
url: '/view2b',
templateUrl: 'forms/empl/searchEmplForm.html',
controllerAs: 'srchC',
controller: 'searchEmplCtrl',
resolve: {
loadOtherCtrl: lazyCtrlLoad('searchEmplCtrl')
}
})
In my other module, I am trying to register controllers, load services..
define([
'angular', 'angularResource'
], function (angular) {
angular.module('myApp')
.getControllerProvider()
.register(ctrl, ...)
But, while loading service below, I need access to $resource which is part of ngResource module in angularResource.
angular.module('myApp')
.getProvider().service('deptService', ['$resource', function ($resource) {
return $resource('/dept/:dept', {dept: '#_dept'});
}])
How can I load ngResource while initalizing the javascript controllers/services lazily?
Take a look to AngularAMD here. It allows you to load controllers in the ui-router without using lazyload. This AngularAMD is used to integrate requireJs and Angular.
$stateProvider
.state('home', {
url: '',
views: {
'#': angularAmd.route({
templateUrl: 'ngApplication/application/shared/layouts/basic/basicTplView.html',
controllerUrl: 'ngApplication/application/shared/layouts/basic/basicTplCtrl.js',
controller: 'basicTplCtrl'
}),
'header#home': angularAmd.route({
templateUrl: 'ngApplication/application/shared/layouts/header/headerView.html',
controllerUrl: 'ngApplication/application/shared/layouts/header/headerCtrl.js',
controller: 'headerCtrl'
})
},
});
Also, you are using requirejs, you can load all the dependencies for an specific controller using the define syntax of requireJs. Let's say you want to create a loginCtroller in a separately file, and this controller depends on another angular service:
define(['app', 'transformRequestAsFormPostService'], function (app) {
app.controller('loginCtrl', ['$scope', '$rootScope', '$sce', '$http', '$state', 'transformRequestAsFormPostService', function ($scope, $rootScope, $sce, $http, $state, transformRequestAsFormPost) {
$scope.login = function () {
/*do something here using the service*/
};
}]);
});
Here, the dependency called transformRequestAsFormPostService is another file, I defined it in the main.js (requireJs confifguration file) and it's defined using the same approach than the loginCtrol. Now I am using it in my project and its working so far so good.
Regards,
Ernesto
I am integrating some Angular and ui-router into my start-up's website and I have come across an issue with getting ui-router and ui-view to work. It lead to wonder what the / in the url property of .state points to. Does it point to where the Angular app is declared or somewhere else? Essentially I'd appreciate any feedback into how I can fix my issue. (See "careers" state in "App Module" code below to see what I am referring to)
As you can see here, it's not currently working.
App Module
var careersApp = angular.module("ultradiaCareers", ["ui.router", "services"]);
careersApp.config(function($stateProvider, $locationProvider){
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
$stateProvider
.state('careers', {
url: "/",
templateUrl: "openings.html",
controller: "CareersController"
})
.state('positions', {
url: "/position/:id",
templateUrl: "position.html",
controller: "PositionsController"
});
});
Controllers
angular.module("ultradiaCareers")
.controller('CareersController', ["$scope", "GetOpenings", function ($scope, GetOpenings) {
"use strict";
GetOpenings.openings.then(function (positions) {
$scope.openings = positions.data;
});
}])
.controller('PositionsController', ["$scope", "$http", "$stateParams", "GetOpenings", function ($scope, $http, $stateParams, GetOpenings) {
"use strict";
GetOpenings.openings.then(function (positions) {
$scope.openings = positions.data;
$scope.positon = positions.data[GetOpenings.getPositionById($scope.openings, $stateParams.id)];
});
}]);
Index HTML
<html>
<head></head>
<body ng-app="ultradiaCareers">
<div ui-view></div>
</body>
</html>
Service for JSON
var careersServices = angular.module("services", [])
.factory("GetOpenings", ["$http", function ($http) {
"use strict";
var GetOpenings = this, i;
GetOpenings.openings = $http.get("/careers/positions.json");
return {
openings: GetOpenings.openings,
getPositionById: function (data, value) {
for (i = 0; i < data.length; i++) {
if (data[i].pid == value) {
return i;
}
}
}
};
}]);
So i've got my code:
(function (ng) {
ng.module('myModuleName')
.provider('myProviderName', ['importedThing', function (importedThing) {
//lots of cool stuff happens in here
}];
}])
.config(['$stateProvider', '$urlRouterProvider', 'importedThing', 'myProviderNameProvider', function ($stateProvider, $urlRouterProvider, importedThing, myProvider) {
window.stateProvider = $stateProvider;
$urlRouterProvider.otherwise(function ($injector, $location) {
$location.path("/pages");
});
}]);
}(angular));
I need to unit test this line for code coverage:
$location.path("/" + myProvider.coolString);
But I can't figure out how. I've seen several people do it with controllers, but not with providers.
I've got the unit test set up like:
beforeEach(function () {
angular.module('dsLocale', function () { }).config(function ($urlRouterProvider) {
$urlRouterProvider.deferIntercept();
$urp = $urlRouterProvider;
$urp.deferIntercept();
});
});
//Lines are commented to represent random stuff I've tried already.
it('should call otherwise', function () {
//$urp.otherwise('/otherwise');
//$location.path("/lastrule");
console.log($location.path());
//local.$emit("$locationChangeSuccess");
expect(true).toBe(true);
});
I feel like it should be as easy as just changing $location.Path to something that doesn't exist, so UIRouter can do it's thing but it doesn't appear to be that easy. Any help is appreciated, and thanks in advance!
just had the same problem. I wanted to test the otherwise functionality, but did not how, i figured out a way and this worked for me.
I am setting the path with location.path, firing the $locationChangeSuccess event and then it works
it('redirects to otherwise page after locationChangeSuccess', function() {
location.path('/nonExistentPath');
rootScope.$emit("$locationChangeSuccess");
expect(location.path()).toBe("/");
});
without the event, the path is the of course /nonExistentPath
--
this is my full test file. Be aware, i am using browserify and the file maybe looks a little different than yours
'use strict';
require('../../../app');
var objectToTest = 'CoreRouterConfig';
describe(objectToTest, function () {
var rootScope,
state,
location;
beforeEach(angular.mock.module('ui.router'));
beforeEach(angular.mock.module('core'));
beforeEach(inject(function ($rootScope, $state, $location) {
rootScope = $rootScope;
state = $state;
location = $location;
}));
it('should respond home state', function() {
expect(state.href('home')).toEqual('#/');
});
it('init path is correct', function() {
rootScope.$emit("$locationChangeSuccess");
expect(location.path()).toBe("/");
});
it('redirects to otherwise page after locationChangeSuccess', function() {
location.path('/nonExistentPath');
rootScope.$emit("$locationChangeSuccess");
expect(location.path()).toBe("/");
});
it('does not redirect to otherwise page without locationChangeSuccess', function() {
location.path('/nonExistentPath');
expect(location.path()).toBe("/nonExistentPath");
});
});
'use strict';
(function () {
angular
.module('systemStatusApp')
.config(function ($stateProvider) {
$stateProvider
.state('app.isomicroservices', {
url: 'isomicroservices',
templateUrl: 'app/isomicroservices/templates/isomicroservices.html',
controller: 'isomicroservicesCtrl',
resolve : {sampledetails : function(){
console.log("resolve");
}
return "asdf";
}
});
});
})();
--
'use strict';
(function () {
angular
.module('isomicroservices')
.controller('isomicroservicesCtrl', 'sampledetails',function (sampledetails) {
console.log("sampledetails"+sampledetails);
});
})();
I think your code maybe can be:
'use strict';
(function () {
angular
.module('isomicroservices')
.controller('isomicroservicesCtrl', ['sampledetails', function (sampledetails) {
console.log("sampledetails"+sampledetails);
});
}])();