Syntax for Extending AngularJS Route Provider - javascript

Hopefully this question doesn't get erroneously marked as a duplicate.
I am attempting to extend the AngularJS $routeProvider, as suggested as a response to a previous question. Unfortunately, this is not working, and I may have the syntax incorrect.
Here is a sanitized version of my "top-level" module:
// app.js
angular.module('app', ['ngRoute', 'ngSanitize'
, 'main'
])
.provider('appRoute', ['$routeProvider', function($routeProvider) {
this.$get = function($http) {
console.log("Instantiaing $rmaRouteProvider");
var universalResolves = {authorize: function($http) {
return $http.get('/svc/authorize/view?urlPath=' + path)
.then(function(response) {
var data = response.data;
if (response.data.result === 'NOT_AUTHORIZED') {
throw "NOT_AUTHORIZED";
}
console.log("finished authorized()");
return data;
});
}
};
var rmaRouteProvider = angular.extend({}, $routeProvider, {
when: function(path, route) {
route.resolve = (route.resolve) ? route.resolve : {};
angular.extend(route.resolve, universalResolves);
$routeProvider.when(path, route);
return this;
}
});
return rmaRouteProvider;
}
}]);
Here is my main.js, where I am attempting to define routes using the appRoute provider instead of the $routeProvider:
angular.module('admin', ['ngRoute', 'ngSanitize', 'ngCsv'])
.config(['appRouteProvider', function(appRouteProvider) {
appRouteProvider.when('/route', {
templateUrl: 'pageTemplate.tmpl.html',
controller: 'pageCtrl'
}
]);
Unfortunately, I get the following error:
Error: [$injector:modulerr] Failed to instantiate module app due to:
[$injector:modulerr] Failed to instantiate module main due to:
[$injector:unpr] Unknown provider: appRouteProvider
http://errors.angularjs.org/1.5.8/$injector/unpr?p0=%24appRouteProvider
minErr/<#https://localhost:8443/js/angular/angular.js:68:12
createInjector/providerCache.$injector<#https://localhost:8443/js/angular/angular.js:4511:19
getService#https://localhost:8443/js/angular/angular.js:4664:39
injectionArgs#https://localhost:8443/js/angular/angular.js:4688:58
invoke#https://localhost:8443/js/angular/angular.js:4710:18
runInvokeQueue#https://localhost:8443/js/angular/angular.js:4611:11
loadModules/<#https://localhost:8443/js/angular/angular.js:4620:11
forEach#https://localhost:8443/js/angular/angular.js:321:11
loadModules#https://localhost:8443/js/angular/angular.js:4601:5
loadModules/<#https://localhost:8443/js/angular/angular.js:4618:40
forEach#http…
As I said, I'm hoping this is an error with my syntax.
Edit: I realize that instatiation of providers is load-order specific. The app.js is the first <script> imported in the application index.html file and should be loaded first.
Edit 2: I have updated this question to the following: Custom Route Provider when is not a function

Related

Angular JS unknown Provider error - $cookieStoreProvider

I am working on an angular application. It was a working application on windows.
Now i switched to mac and trying to build the same but after the build when I am opening the application on browser it is throwing console error: Uncaught Error: [$injector:unpr]
https://code.angularjs.org/1.7.8/docs/error/$injector/unpr?p0=$cookieStoreProvider%20%3C-%20$cookieStore
Here is the app.js:
angular
.module('xyz', [
'ui.router',
'Commons' ,
'ngCookies',
'ngMask',
'ui.bootstrap.datetimepicker',
'btorfs.multiselect',
'oitozero.ngSweetAlert'
])
.constant('GLOBAL_CONSTANTS', {
})
.config(['$urlRouterProvider', '$httpProvider', '$stateProvider', initializeConfigurationPhase])
.run(['$rootScope', '$cookieStore', 'httpService', 'notificationService', initializeRunPhase]);
function initializeRunPhase($rootScope, $cookieStore, httpService, notificationService) {
$rootScope.currentItem = 0;
$rootScope.baseUrl = "someurl";
// $rootScope.baseUrl = "http://localhost";
$rootScope.loggedIn = false;
if($cookieStore.get('access_token')) {
$rootScope.loggedIn = true;
notificationService.connect();
}
if(!$cookieStore.get('userCountryCode')) {
fetchUserCountry();
} else {
$rootScope.userCountryCode = $cookieStore.get('userCountryCode');
}
function fetchUserCountry () {
httpService.getWithoutData(url, true).then(function(response){
$cookieStore.put('userCountryCode',response.country_code);
$cookieStore.put('city',response.city);
$cookieStore.put('region_name',response.region_name);
});
}
}
Let me know if i am missing something or doing something wrong.
As already said by #Petr Averyanov, $cookieStore is deprecated from angular 1.6
look here
$cookieStore is now deprecated as all the useful logic has been moved
to $cookies, to which $cookieStore now simply delegates calls.
install angular 1.5 and you won't get that error

How can I set Angular values from a config file?

I have an app that I have inherited that I have to support. So far it had only run on one server and we want to run it on different servers. We found hard coded references to the server name all over the place in python server code and C++ client code. It was easy enough to change those to read the server name from a config file. But now I find is a js module this code:
angular.module('app.config', []).constant('config', {"api":"http://foo.bar.com:8001/"});
How can I change this so that the value for the server is read dynamically from a config file or some other means that would not require it to be hard coded?
Here is an update with what I have tried:
Originally, my code had this:
angular.module('app.config', []).constant(
'config', {"api":"http://foo.bar.com:8001/"}
);
and I changed it to this:
angular.module('app.config').controller('myCtrl',
function($scope, $http) {
$http.get('./config.json')
.then(function(response) {
$scope.api = response.data;
});
});
and I got this:
error Module 'app.config' is not available!
Then I changed it to:
angular.module('app.config', [] ).controller('myCtrl',
function($scope, $http) {
$http.get('./config.json')
.then(function(response) {
$scope.api = response.data;
});
});
And then I get:
Error: [$injector:unpr] Unknown provider: configProvider <- config <- workitem
I feel I am very close, I just need a bit more help.
Another update:
I tried this:
angular.module('app').controller('home', ['$scope', homeCtrl]);
angular.module('app').controller('workitem', ['$scope', '$routeParams', '$sce', '$timeout', '$http', 'config', workitemCtrl]);
},{"./home/home.js":3,"./workitem/workitem.js":4,"angular":10,"angular-route":6,"angular-sanitize":8,"bootstrap-treeview/src/js/bootstrap-treeview.js":11}],2:[function(require,module,exports){
module.exports = function($scope,$http) {
$http.get('config.json').success(function(reponse) {
console.log("reponse --> "+reponse.api);
$scope.api = reponse.api;
});
}
But then of course app.config was not getting defined. How could I do this an still define app.config?
I just tried this:
var my_config = {};
$.getJSON("config.json", function(data) {
$.each(data, function(key, val) {
my_config[key] = val;
});
});
but I get my_config is not defined when I use it down in the controller. How can I make that variable available in the controller?
Try This
angular.module('app.config', [])
.constant('bbConfig',{
"api":"http://foo.bar.com:8001/"
});
In controller
angular.module('app.config', [])
.controller('MainCtrl',['$scope', 'bbConfig' , function ($scope, bbConfig){
console.log(bbConfig.api)
}]);
Create a service to read the config (json file) or make a call to server and store the response URL in LocalStorage like the following. You can access it from every where
$localStorage.api = response.Url ; // http://foo.bar.com:8001/
I was finally able to get this working by doing this up front:
angular.module('app').value('config', {
api: ''
});
angular.module('app').run(function($rootScope, $http, config) {
$http.get('config/config.json').then(function(response) {
config.api = response.data.api;
$rootScope.$broadcast('config-loaded');
});
});
Wrapping the main code in:
var init = function(){
}
And adding this at the end:
if (config.api) {
init()
} else {
var configLoaded = scope.$on('config-loaded', function() {
init();
configLoaded();
});
}
You can do:
Use ngConstant build task to wrap your standalone config file in JSON format into the includable angular.config data.
Suppose you have app/config.json file:
{
"myFirstCnt": true,
"mySecondCnt": { "hello": "world" }
}
Then after running the ngConstant task in you build you'll get dist/config.js (output) will be :
define(["require", "exports"], function(require, exports) {
return angular.module("my.module.config", ["ngAnimate"])
.constant("myFirstCnt", true)
.constant("mySecondCnt", { "hello": "world" })
.constant("myPropCnt", "hola!");
});
Gulp plugin, Grunt plugin, more on ngConstant
Use service to load the JSON file immediately after you app bootstraps in service or in the controller:
should avoid this:
app.controller('myCtrl',
function($scope, $http) {
$http.get('PATH_TO/config.json').then(function(response) {
$scope.myWelcome = response.data;
});
}
);
More on that way example here: Reading in JSON through Angular Resources Service
UPD 12-06
For parsing loaded JSON try this:
for (var name in data) {
if (data.hasOwnProperty(var)) {
my_config[var] = data[var];
}
}

ngResource/$resource not injected correctly

The current task is to write a client for an API. The $resource module is not getting injected correctly. I have injected ngResource to the module, and then also passed it into the factory declaration. However inside the controller, if I try to console.log($resource), I get the following error:
TypeError: 'undefined' is not a function (evaluating '$resource('https://ourlink.nl',options)')
I am convinced the issue is happening/not happening in app.js, but receptive to input if you have other ideas. Can you help me spot the problem?
restClient.js
function restClient ($resource) {
'use strict';
var options = {};
init();
return {
endpoint: self.endpoint,
sendRequest: sendRequest
};
function init () {
self.endpoint = 'https://ourlink.nl';
}
function sendRequest () {
$resource('https://ourlink.nl', options);
return true;
}
}
module.exports = restClient;
app.js
var angular = require('angular');
// imports
require('angular-resource');
(function (angular, config, loaders, controllers, services, providers) {
'use strict';
angular
.module('at.annabel', [
'ngLocale',
'ngRoute',
'ngResource',
'ngSanitize',
'pascalprecht.translate',
'ui.bootstrap'
])
// constants
.constant('translations', config.translations)
// config
.config([
'$locationProvider',
'config.BASE_PATH',
providers.locationProvider
])
// services
.factory(
'restClient',
['$resource', services.restClient]
)
// controllers
.controller(
'PlaceholderController',
[controllers.PlaceholderController]
)
;
}
))(
angular,
// config
{
menu: require('./config/menu').config
...
}
},
// loaders
{
localeLoader: require('./config/locale-loader')
},
// controllers
{
PlaceholderController: require('./modules/placeholder/placeholder-controller')
},
// services
{
restClient: require('./services/restClient')
},
//providers
{
locationProvider: require('./config/location-provider')
}
);
It turned out to be there the whole time. Since the app does not invoke restClient.js in the browser, I was only seeing the module invoked in test. The test runner wasn't properly set up for $resource, and $resource needed to be injected into the module by the test. Thanks to everyone who took the time to read and investigate. I got caught up on the app.js file, because it is so unconventional, but turns out the whole file is legit.

AngularJS: Failed to instantiate module error

i know this question has already been asked, but i could not find the answer to my personal case. I'm sure it's a stupid thing i didn't notice but i'm not getting out of it.
I'll post all the code i have (it's not that much) because i can not find the real origin of the error.
This is my app.js file:
'use strict';
var myApp = angular.module('myApp', [
'ngRoute',
'appControllers'
]);
myApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/faq', {
templateUrl: 'faq/faq.html',
controller: 'FaqCtrl'
}).
when('/log', {
templateUrl: 'log/log.html',
controller: 'LogCtrl'
}).
[...]
when('/settings', {
templateUrl: 'settings/settings.html',
controller: 'SettingsCtrl'
}).
otherwise({redirectTo: '/homepage'});
}]);
While here is where i hold my controllers, controllers.js:
'use strict';
/* Controllers */
var appControllers = angular.module('appControllers', []);
appControllers.controller('FaqCtrl', [function() {
}]);
appControllers.controller('HomepageCtrl', [function() {
}]);
[...]
appControllers.controller('SettingsCtrl', function($scope, $http) {
/*
$scope.myData = {};
$scope.myData = function(item, event) {
var response = $http.get("myURL");
response.success(function() {
alert("ok");
});
response.error(function() {
alert("error");
});
*/
});
And here is settings.html:
<div ng-controller="SettingsController" >
<button ng-click="myData.doClick(item, $event)">Send AJAX Request</button>
<br/>
Data from server: {{myData.fromServer}}
</div>
Now, if i run it with the code inside SettingsCtrl commented it works fine, but if i decomment it, the page does not end its loading (even if i don't go to the Settings section) and the error is this:
Error: [$injector:modulerr] Failed to instantiate module myApp due to:
[$injector:modulerr] Failed to instantiate module appControllers due to:
[$injector:nomod] Module 'appControllers' 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.
What did i miss?
I'm sure it will be a stupid thing, but i'm a newbie with AngularJS.
Thanks in advance.
When you uncomment the curly braces are not closed properly.
appControllers.controller('SettingsController', function($scope, $http) {
$scope.myData = {};
$scope.myData = function(item, event) {
var response = $http.get("myURL");
response.success(function() {
alert("ok");
});
response.error(function() {
alert("error");
});
}
});
http://plnkr.co/edit/4sltz2Bwai9zm9FLkyC7?p=preview
One more issue, the controller name is not matching but you probably have figured it out already.
Looks like you didn't include the controller file in your index.html
you lost a "}"
appControllers.controller('SettingsCtrl', function($scope, $http) {
$scope.myData = {};
$scope.myData = function(item, event) {
var response = $http.get("myURL");
response.success(function() {
alert("ok");
});
response.error(function() {
alert("error");
});
}
});

All AngularJS Controllers Not Loading with LazyLoad

I am trying to lazy load my controllers for my AngularJS app I built along side with requireJS. I have created a custom "lazyLoad" library that creates a resolve object in app.config() routes (also I am using ui-router). If I code the state (without my library) to look like so it works
define(['angular', 'lazyLoader', 'uiRouter'], function(angular, lazyLoader, uiRouter){
var app = angular.module('myApp', ['ui.router']);
app.config(function ($stateProvider, $urlRouterProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {
window.lazy = {
controller: $controllerProvider.register,
directive: $compileProvider.directive,
filter: $filterProvider.register,
factory: $provide.factory,
service: $provide.service
};
$urlRouterProvider.otherwise('/');
$stateProvider
.state('campaigns', {
url:'/campaigns',
views: {
"top-nav" : {
templateUrl: 'views/home/top-nav.html',
resolve : {
load : ['$q', '$rootScope', function($q, $rootScope){
var d = $q.defer();
require(['../app/controllers/header-controller'], function() {
$rootScope.$apply(function(){
d.resolve();
});
});
return d.promise;
}]
}
},
"fullpage": {
templateUrl: 'views/home/index.html',
resolve : {
load : ['$q', '$rootScope', function($q, $rootScope){
var d = $q.defer();
require(['../app/controllers/home-controller'], function() {
$rootScope.$apply(function(){
d.resolve();
});
});
return d.promise;
}]
}
//controller: 'home-controller'
}
}
});
});
return app;
});
If I attempt to replace the resolve object with my library function it looks would look like this:
define(['angular', 'lazyLoader', 'uiRouter'], function(angular, lazyLoader, uiRouter){
and
.state('home', lazyLoader.route({
url:'/',
views: {
"top-nav" : {
templateUrl: 'views/home/top-nav.html',
controllerUrl: '../app/controllers/header-controller'
},
"fullpage": {
templateUrl: 'views/home/index.html',
controllerUrl: '../app/controllers/home-controller'
}
}
}));
lazyLoader.js
define(function () {
'use strict';
function LazyLoader() {}
LazyLoader.prototype.route = function(config){
var controllerPath;
if(config && config.views){
var singleView = Object.keys(config.views);
for(var i in singleView){
var viewName = singleView[i];
controllerPath = config.views[viewName].controllerUrl;
delete config.views.controllerUrl;
config.views[viewName].resolve = {
load : ['$q', '$rootScope', function($q, $rootScope){
var d = $q.defer();
require([controllerPath], function() {
$rootScope.$apply(function(){
d.resolve();
});
});
return d.promise;
}]
};
}
}
return config;
}
return new LazyLoader();
});
Example Controller
define(['app/module'], function (module) {
lazy.controller('header-controller', ['$scope', function ($scope) {
// stuff here
}]);
});
On a side note I plan on implementing something better than attaching lazy variable to window.
When I code the router like the first example it works. When I use my lazyLoader the one of the two views loads it's controller, the second view's controller's file is started to load (console.logs at the beginning show this) but it cannot resolve "module" in the example above.
link to error: AngularJS Error
Again this issue only happens when using my lazyloader which is producing the same resolve object that I have hard coded in for the version that works.
I have searched high and low and there are a lot of resources out there but I could not find anything that addressed this issue.
Any advice is appreciated!
You are taking too much pain to do lazy loading of controllers & services. There is simple approach to lazy load files with ocLazyLoad. This article might help you resolve the same issue.
https://routerabbit.com/blog/convert-angularjs-yeoman-spa-lazyload/
What you should do is
Add a reference of ocLayzLoad & updated JS files’ reference to load on demand from app.js or .html file of their views.
`bower install oclazyload --save-dev`
Now load the module ‘oc.lazyLoad’ in application. Update app.js file
angular
.module('helloWorldApp', [
'ngCookies',
'ngResource',
'ngRoute',
'ngSanitize',
'oc.lazyLoad',
])
Load JS file by adding reference of JS in .html file
<div oc-lazy-load="['scripts/controllers/about.js', 'scripts/services/helloservice.js']">
<div ng-controller="AboutCtrl as about">
Your html goes here
</div>
</div>
If you using Grunt, update Gruntfile to uglyfy, renamed file name & update references in the final .html or .js file.
On the 'myApp' module definition, shouldn't you be returning app variable instead of myApp?
And to avoid exposing lazy to window, you could define it as a property of app variable, this way when you define new functions, you require app first and you can use it:
app.js:
app.lazy = {
controller: $controllerProvider.register,
directive: $compileProvider.register,
filter: $filterProvider.register,
factory: $provide.factory,
service: $provide.service
};
...
return app;
controller.js:
define(['app'], function (app) {
app.lazy.controller('header-controller', ['$scope', function ($scope) {
// stuff here
}]);
});

Categories

Resources