Configure AngularJS routes to deep path using $window - javascript

I have a Rails app which has some complex routing. My Angular application exists in a deep URL such as /quizzes/1
I was hoping to do this the Angular was by injecting $window into my routes configuration and then sniffing $window.location.pathName. This does not seem possible as the application throws an "Unknown provider: $window from myApp" at this stage.
Is there a best-practice way to handle this with Angular? The reason I would like to do this is to use HTML5 mode while the app lives in a deep directory.
Here's an example of what I was hoping for, http://jsfiddle.net/UwhWN/. I realize that I can use window.location.pathname at this point in the program if it's the only option.
HTML:
<div ng-app="myApp"></div>
JS:
var app = angular.module('myApp', [])
app.config([
'$window', '$routeProvider', '$locationProvider',
function($window, $routeProvider, $locationProvider) {
var path = $window.location.pathname
// Coming Soon
// $locationProvider.html5Mode(true)
$routeProvider
.when(path + '/start', {
controller: 'splashScreenController',
templateUrl: 'partials/splash-screen.html'
})
.when(path + '/question/:id', {
controller: 'questionController',
templateUrl: 'partials/question-loader.html'
})
.otherwise({
redirectTo: path + '/start'
})
}])

Only constants and providers can be injected into config block. $window isn't injectable into your config block because $window is a service.
From Angular docs:
Configuration blocks - get executed during the provider registrations and configuration phase. Only providers and constants can be injected into configuration blocks. This is to prevent accidental instantiation of services before they have been fully configured.
And, you don't need $window service there anyway. Just use <base> tag:
<base href="/quizzes/1/" />
and keep your routes relative to it.

Related

Error when injecting a service or factory in config block

i'm trying to make a blog using angular 1.6, all works fine except when i created a service and inject into config file. Test directive works fine, only breaks when inject myService service/factory.
app.coffee
app = angular.module 'dts',['ngRoute']
app.service 'myService', ->
this.asd = ""
app.directive 'ngHello', ->
return {
restrict:'E'
replace: true
template: "<h1>Hola mundo</h1>"
link: (scope,element,attrs)->
}
config.coffee
app = angular.module 'dts'
app.config ["$locationProvider","$routeProvider","myService", ($locationProvider,$routeProvider,myService)->
$routeProvider
.when "/",
controller: "mainCtrl"
templateUrl: "/app/views/index.html"
.when "/blog",
controller: "blogCtrl"
templateUrl: "/app/views/blog/index.html"
.when "/blog/post/:id",
controller: "blogCtrl"
templateUrl: "/app/views/blog/single.html"
.when "/contact",
controller: "contactCtrl"
templateUrl: "/app/views/contact.html"
.otherwise '/'
$locationProvider.html5Mode
enabled: true
requireBase: false
]
script includes
script(src="/js/libs/angular.min.js")
script(src="/app/modules/angular-route.min.js")
script(src="/app/app.js")
script(src="/app/services/slugs.js")
script(src="/app/config.js")
script(src="/app/controllers/main.js")
script(src="/app/controllers/blog.js")
What i'm doing wrong?
I searched about problems or deprecating about service or factory on 1.6 version, but i can't find nothing. I downgrade angular to 1.5.6 and does not works too.
I tried to move service/factory to app file, but breaks too (before i create it on services.js)
you have to inject myServiceProvider in config , you cannot inject service in config function
From the Docs:
Module Loading & Dependencies
Configuration blocks - get executed during the provider registrations and configuration phase. Only providers and constants can be injected into configuration blocks. This is to prevent accidental instantiation of services before they have been fully configured.
— AngularJS Developer Guide - Modules (Loading & Dependencies)
Route tables can not be created or changed by services.
On the other hand, services are injectable in the resolve functions of a route table as those functions are invoked during the run phase of an application.

AngularJS undefined Controller using require

I am using requireJS in my application.
Whenever i tried to register controller on my module it said that the controller is not defined. Here is my controller which resides on login.controller.js
function LoginController() {
}
and here's my module code:
require('angular')
require('#uirouter/angularjs');
require('./service/storage')
require('./controller/login.controller')
angular.module('SecurityModule', ['ui.router'])
.controller('LoginController', LoginController);
// Routing
angular.module('SecurityModule')
.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.hashPrefix('');
$stateProvider.state('login', {
url: '/login',
templateUrl: '/app/resources/view/security/login.html',
controller: 'LoginController',
});
})
;
When i checked my bundled.js the declaration of LoginController appears first. So why is it still undefine?
Thanks.
NOTE that im using browserify (which then uses commonJS) to bundle my files.
As the documentation states:
A module is a collection of configuration and run blocks which get
applied to the application during the bootstrap process. In its
simplest form the module consist of collection of two kinds of blocks:
Configuration blocks - get executed during the provider registrations
and configuration phase. Only providers and constants can be injected
into configuration blocks. This is to prevent accidental instantiation
of services before they have been fully configured.
angular.module('myModule', []).
config(function(injectables) { // provider-injector
// This is an example of config block.
// You can have as many of these as you want.
// You can only inject Providers (not instances)
// into config blocks.
}).
run(function(injectables) { // instance-injector
// This is an example of a run block.
// You can have as many of these as you want.
// You can only inject instances (not Providers)
// into run blocks
});

AngularJS 1.5 Controllers in Separate Files

I have a hard time understanding this. I'm attempting to put controllers in separate files so that they only deal with 1 thing, ideally, a partial view
My folder structure is like this...
My app.js file is like this.
angular.module('mikevarela', ['ui.router', 'mikevarela.controller.home', 'mikevarela.controller.about', 'mikevarela.controller.audio'])
.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
templateUrl: '../partials/home.partial.html',
controller: 'HomeController'
})
.state('about', {
url: '/about',
templateUrl: '../partials/about.partial.html',
controller: 'AboutController'
})
.state('audio', {
url: '/audio',
templateUrl: '../partials/audio.partial.html',
controller: 'AudioController'
});
});
and my controllers each have a module like this...
angular.module('mikevarela.controller.home', [])
.controller('HomeController', ['$scope', function($scope) {
$scope.title = 'Mike Varela Home Page';
}]);
My issues comes with the intial app declaration. I don't want to have to inject all the controllers in the main array app definition, that would be cumbersome and long winded. Isn't there a way to define the controller at the controller file. Kind of like this
angular.module('mikevarela', []).controller('HomeController', ['$scope', function($scope) {
// stuff here
}]);
Use angular.module('mikevarela').controller..... in subsequent files.
angular.module('mikevarela',[]).controller.....
is equivalent to redefining your app. The second param is requires array.
Quoting official angular.module docs
requires
(optional)
!Array.=
If specified then new module is being created. If unspecified then the module is being retrieved for further configuration.
About your Controllers...
I think you're loading the controllers incorrectly.
You don't need to declare controllers as a dependency. Rather stating module.controller('yourController)` makes that controller available throughout the module.
If your controllers are in separate files, all you need to do to make it available is load it in with a script tag. e.g.
<script src="app.js"></script>
<script src="controller1.js"></script>
<script src="controller2.js"></script>
About your Application Structure...
This is not related to your question, but just coming from someone who's developed using Angular, I'd recommend not grouping your application by controllers/ by rather by feature. See: https://scotch.io/tutorials/angularjs-best-practices-directory-structure

How to create Tabs using AngularJs and Bootstrap - Need to modify existing code

I have found on stackoverflow a good example of how to create Tabs using AngularJS and Bootstrap, but I have a problem. The original code is using an old library of Angular (1.0.4) and if I switch to the current one (1.4.7) the script does not work anymore.
Here is the original code on Plunker
Here is the original Post
Here is what I've tried so far to change:
var app = angular.module('plunker', ['ngRoute']);
app.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/jobs', {
templateUrl: 'jobs-partial.html',
controller: JobsCtrl
})
.when('/invoices', {
templateUrl: 'invoices-partial.html',
controller: InvoicesCtrl
})
.when('/payments', {
templateUrl: 'payments-partial.html',
controller: PaymentsCtrl
})
.otherwise({
redirectTo: '/jobs'
});
});
Where is the problem?
As of AngularJS 1.2 and later:
ngRoute is now its own module
As of AngularJS 1.3 and later:
...$controller will no longer look for controllers on window. The old behavior of looking on window for controllers was originally intended for use in examples, demos, and toy apps. We found that allowing global controller functions encouraged poor practices, so we resolved to disable this behavior by default.
Therefore [1] adding ngRoute as a dependency to your module and [2] including the angular-route.js source file and [3] explicitly registering the controllers fixed it for me:
http://plnkr.co/edit/KJyFqf2vf74IidY26vxu?p=preview
[1]
var app = angular.module('plunker', ['ngRoute']);
[2]
<script src="http://code.angularjs.org/1.4.7/angular-route.js"></script>
[3]
app.controller('TabsCtrl', TabsCtrl);
app.controller('JobsCtrl', JobsCtrl);
app.controller('InvoicesCtrl', InvoicesCtrl);
app.controller('PaymentsCtrl', PaymentsCtrl);
Older versions of angular allowed for the use of global functions as controllers.
Support for that was dropped in version 1.3 and you need to register controllers as a module component.
Also ngRoute is a separate include now and must be injected as a module dependency
Here's an updated demo using angular 1.4.
Note that controllers are registered using:
angular.module('plunker')
.controller('TabsCtrl',TabsCtrl)
.controller('InvoicesCtrl',InvoicesCtrl)
.controller('PaymentsCtrl',PaymentsCtrl)
And in routing the controller is now string. Also ngRoute is included as module dependency
var app = angular.module('plunker', ['ngRoute']);
app.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider.
when('/jobs', {templateUrl: 'jobs-partial.html', controller: 'JobsCtrl' }).
DEMO

Yeoman and angular - routing doesn't work

I'm trying start developing angular apps with yeoman. It may sounds stupid, but I have a problem with creating routes using yo:angular route.
When I create new route using:
yo:angular route foo
yeoman creates:
app/scripts/controllers/foo.js (controller)
app/views/foo.html (view)
app/test/spec/controllers/foo.js (testing the controller)
in app.js it creates:
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/foo', {
templateUrl: 'views/foo.html',
controller: 'FooCtrl'
})
.otherwise({
redirectTo: '/'
});
});
so everything should work fine. Unfortunately the route doesn't work - when I try open
http://localhost:9000/foo
I get following error:
Cannot GET /foo
The idea of routes in yeoman looks pretty easy and I'm not sure where the problem is.
Did you enable HTML5 mode in your Angular application? If not, the URL would be:
http://localhost:9000/#/foo
And if you have enabled HTML5 mode in your Angular application, you have to make sure whatever server you're using has been configured to handle all routes as they were the root of the application.

Categories