I'm having some trouble injecting a service into a controller in a Yeoman AngularFire app.
Here is the controller(which is included by the Yeoman generator) that I am trying to inject user into:
angular.module('myYoApp')
.controller('ChatCtrl', function ($scope, user, Ref, $firebaseArray, $timeout) { ....
Which produces this Unknown provider error:
angular.js:12798 Error: [$injector:unpr] Unknown provider: userProvider <- user <- ChatCtrl
Strangely it works fine in my custom controller, allowing the user to be accessed in the associated view.
angular.module('myYoApp')
.controller('myCtrl', function ($scope, user, Auth, Ref, $firebaseArray, $firebaseObject, $timeout) { ....
I have no idea why the user service would be injectable in my custom controller but not in the Yeoman generated ChatCtrl. I've also looked all over the project and can't seem to find where the user service is coming from. But it's clearly somewhere in the app if my custom service can use it.
I've also tried using $user in place of user but that didn't fix it.
Cheers for any help figuring this out!
Ok.I managed to solve this. It was an oversight in the routes.js. The Yeoman angularfire-generator adds built-in routes security/authentication which is added to a route to easily block it from being accessed unless the user is logged in.
As a result, the user service can only be injected into a controller if the route uses $routeProvider.whenAuthenticated in place of $routeProvider.when.
Regular unsecured route looks like this:
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
Secured route looks like this:
$routeProvider
.whenAuthenticated('/chat', {
templateUrl: 'views/chat.html',
controller: 'ChatCtrl'
})
Related
Some I'm new to routing and single page web apps, but I've been trying to learn Angular correctly. There's some trouble I'm experiencing with it however and a few weird questions. I followed a guide on structuring your directory and mine looks something like this:
app/
components/
profile/
profile.html
ProfileModel.js
ProfileController.js
ProfileFactory.js
app.module.js
app.routes.js
My main module is located in app.module.js and is dependency injected with ngRoute and profile.app (the module for profile view from ProfileModel.js). It is declared like this:
angular
.module('app', ['ngRoute', 'profile.app'])
.controller('MainController', MainController);
function MainController() {
this.message = 'This is the home page';
}
Then in my app.routes.js file, I have declared all the routes the applications needs (so far only one, which is profile):
angular
.module('app')
.config(routeConfig);
routeConfig.$inject = ['$locationProvider', '$routeProvider'];
function routeConfig ($locationProvider, $routeProvider) {
$routeProvider
.when('/user/:user_id', {
templateUrl: '/app/components/profile/profile.html',
controller: 'ProfileController',
controllerAs: 'profile'
}
)
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
}
This is my ProfileController.js:
angular
.module('app.profile')
.controller('ProfileController', ProfileController);
ProfileController.$inject = ['ProfileFactory', '$routeParams'];
function ProfileController(ProfileFactory, $routeParams) {
var vm = this;
vm.user_id = $routeParams.user;
console.log($routeParams.user_id);
vm = ProfileFactory.userProfile(vm.user_id); //Gets the profile of the user and sets to to vm
}
So I have two main questions. $routeParams.user_id is logged as nothing despite I have defined the route in app.routes.js. This is weird because I have an ng-view directive in my index.html (the HTML file that includes every single .js file). Which means that I should have immediate access to the routing parameters once the controller and its dependencies are instantiated. However, when I go to http://example.com/user/1, I get nothing logged (undefined).
My second question is I included ngRoute as a dependency in profile.app and my main module (in which profile.app is a dependency). However, I later removed ngRoute from profile.app as a dependency, yet I left the injection of $routeParams inside my ProfileController and AngularJS didn't complain at all. This seems weird because the dependency is no longer explicitly present inside profile.app. So how come I can still seemingly inject $routeParams despite not having ngRoute in my profile.app module? Is it because it is getting ngRoute from the main module?
I believe the problem is that you are setting controllerAs to 'profile' but then in the controller you write var vm = this;
These two need to be the same so you could write controllerAs: 'vm', or var profile = this;
I am getting the unknown provider error and I am not sure why. My angular controller is not finding the service that I have created. My Service is defined as:
var app = angular.module('losApp');
app.service('ClientService', ['$scope','$http','$q',function($scope,$http,$q){
var client = {};//empty oject that will store multiple function
return client; //return the client object
}]);
Also, my controller is defined as:
var app = angular.module('losApp');
app.controller('DashboardController', ['$scope', '$modal','ClientService',function($scope, $modal,ClientService){}
In my index.html, the scripts tags are declare as follows:
<script src="js/app.js"></script>
<script src="js/services/ClientService.js"></script>
<script src="js/controllers/DashboardController.js"></script>
In app.js, I am using ui-router module to handle routing for the application.
var app = angular.module('losApp', ['ngMessages', 'ui.bootstrap', 'angularFileUpload', 'ui.router', 'summernote', 'angucomplete-alt', 'ngCookies']);
app.config(function($stateProvider,$urlRouterProvider,$locationProvider, $interpolateProvider){
$urlRouterProvider.otherwise('/'); //redirects to this page is
$stateProvider.state('/',{
url:'/',
views : {
// the main template will be placed here (relatively named)
'':{
templateUrl: '/js/pages/dashboard.html',
controller: 'DashboardController'
}
}
});
});
In browser console log and clicked on the angular error message. Additionally, I followed what angularjs docs suggested, but still no success.
What I am doing wrong and thanks in advance.
I found out why I was getting unknown provider.It was because I had injected the $scope object into the factory, which is not allowed.
I have seen the other answers and so far nothing has helped me. I get this error with the following code in a file:
angular.module('myApp.page', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/page/:pageId', {
templateUrl: 'page/view.html',
controller: 'PageCtrl',
resolve: {
data: function($q, $http, $routeParams) {
var deferred = $q.defer();
$http({method: 'GET', url: 'http://....' + $routeParams.pageId})
.then(function(data) {
deferred.resolve(data);
});
return deferred.promise;
}
}
})
}])
.controller('PageCtrl', function ($scope, $rootScope, data) {
//do stuff
}
And in the app.js I have this:
angular.module('myApp', [
'ui.bootstrap',
'ngRoute',
'ngTouch',
'ngResource',
'myApp.page'
]).
config(['$routeProvider', function($routeProvider) {
$routeProvider.otherwise({redirectTo: '/'});
}]).
config(['$provide', Decorate])
Everything was working correctly and I fetched the data with the HTTP method with no problems, until I started using the Q library and moved the data fetching into the config section. Any tips? None of the other answers seem to work. Thanks in advance!
You issue is due to the fact that you are using ng-controller directive to instantiate the controller PageCtrl which takes a dynamic dependency data which is only created by the router. So when you inject a dynamic dependency via router resolve and having the router instantiate the controller, you do not need to and should not instantiate the controller via ng-controller it will simply fail due to the lack of dependency availability from the injector. router will manage the instantiation of the controller and setting it up for the respective view for you.
So just remove ng-controller from your view also make sure the partial represented by the route is complete enough to represent the view related to the controller functionality. Also i have seen it is a good practice not to start with a partial view with ng-controller and instantiate with route which will help making that partial view more reusable with a different controller. Also while creating a unit test you can easily mock the dynamic dependency and feed it via the $controller service.
I am new to angular and am trying to build a small application, I am using .Net for my web api and have coded a HttpResponseMessage Post method that returns a JWT. Before I start to use the JWT I just want to hit the back end, get the JWT and if it comes back redirect to another view. I am using UI Router to do this
My code looks something like this:
controller
(function () {
function LogInController($scope, $http, $state) {
$scope.signOn = function () {
$http.post('http://localhost:route to my backend').then(function (response) {
if (response.data.token) {
$state.go("main");
} else {
alert('you do not have a token');
}
});
};
};
app.controller("LogInController", LogInController);
}());
Html:
Sign in
app.js
"use strict";
//defines the main module
var app = angular.module("app", ["ui.router"]);
app.config(function ($stateProvider) {
$stateProvider
.state("main", {
url: "/main",
templateUrl: "MedOrders.html",
controller: "MedOrdersCtrl",
});
});
this currently works, it hits my back end and shows me my token. I tried to change it to the following and got a ton of injector errors
app.js using UI router
var app = angular.module("app", ["$state"]);
app.config(function($state) {
$stateProvider
.state("main", {
url: "/main",
templateUrl: "where/my/view/lives.html",
controller: "newViewsController"
});
});
I am trying to start off simple which is why I do not have a login service and that may be my problem, but I am not quite sure, when I try to run this UI router fails silently. I end up still on the log on page but with the #/main appended. Should I be doing something to force this redirect the angualr way? And is there a way to get error messages from UI router?
You are using the ngRoute module as dependency while you are using ui.router in the rest of the code.
Changing the dependency to ui.router will solve the errors at least
var app = angular.module("app", ["ui.router"]);
What would be the best way to split AngularJS application into smaller pieces/module? For example if I have a blog post and commenting enabled for that, I think I could break it down to modules like "posts" and "comments"(?) (maybe not the best example, but the idea is to split the application logic into separate modules rather than building a huge one-module-app).
I've tried to bootstrap both modules in the separate DOM nodes and use routing in both of the modules accordingly. There are few problems:
As a "single-page" application I'm bootstrapping comments module to be used even on the front page even though it's not used there.
Since I'm not able to use multiple ng-views inside ng-app, I'm forced to write all the wrappers for my modules in the index.html view and bootstrap them? Should it be like that? Seems a bit wrong. How/where should I bootstrap those?
Are there any tips for the routing? Should I spread those in the modules or should I combine them all together somehow? (creating one "blog" module to include "posts" and "comments" modules as dependencies would still make it hard to define for example the "/post/:id" routing..?)
index.html
<div class="post"><ng-view></ng-view></div>
<div class="comments"><ng-view></ng-view></div>
javascript.js
angular.module('posts', []).config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/', {
'template': 'Showing all the posts',
'controller': 'postCtrl
})
.when('/post/:id', {
'template': 'Showing post :id',
'controller': 'postCtrl
});
}]);
angular.module('comments', []).config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/post/:id', {
'template': 'Showing post :id comments',
'controller': 'CommentsCtrl'
});
}]);
angular.bootstrap($('.post'), ['posts']);
angular.bootstrap($('.comments'), ['comments']);
I would divide the app in "view modules" and these sub modules.
Then I use the $routeProvider to switch between the views. I define the different routing config in each module.
If I need further submodules, I load these with ng-include.
/* App Module */
angular.module('MyApp', ['MyApp.home', 'MyApp.blog'])
.config( function myAppConfig ( $routeProvider ) {
'use strict';
$routeProvider.otherwise({ redirectTo: '/home' });
});
/* home Module */
angular.module('MyApp.home', [])
.config(['$routeProvider', function config( $routeProvider ) {
$routeProvider.when('/home', {
controller: 'HomeController',
template: '<p>This is my Home</p>'
});
}]);
I created a little repository on github to explain this.
You can define routes in the submodules:
angular.module('app', ['ngRoute', 'app.moduleX'])
.config(function($routeProvider, $locationProvider) {
$routeProvider.when('/home', {
templateUrl: 'partials/home.html',
controller: 'HomeCtrl'
});
//Handle all exceptions
$routeProvider.otherwise({
redirectTo: '/home'
});
})
angular.module('app.moduleX', []).config(function($routeProvider) {
$routeProvider.when('/settings', {
templateUrl: 'partials/settings.html',
controller: 'SettingsCtrl'
});
})
I also wrote a blog post about this topic.
We're doing something similar with a portal app and sub-apps. A few things we've discovered:
Only one "app" can have routes and routeParams. Because of this, if the "sub-app" needs access to the $routeParams, you either have to go "old school" for URL parsing, or use an event service.
Speaking of events, there is no Angular service for the apps to communicate, so you'll need to roll your own event service talking to root scope for both apps and inject it into both apps.
I can't see where we used ng-view for the "sub-app". Apparently bootstrapping directly to an element works similarly.
Because only one app can have routes, the apps should be bootstrapped in order. So something like this:
$( function () {
$.when(angular.bootstrap($('.post'), ['posts'])).done( function() {
console.log('POSTS: bootstrapped');
//Manually add the controller to the comments element. (May or may not be
//necessary, but we were doing something that required it to work.)
$('.comments').attr('ng-controller', 'CommentsCtrl');
$.when(angular.bootstrap($('.comments'), ['comments'])).done( function() {
console.log('COMMENTS: bootstrapped');
});
});
});
I hope you can use "ui-router" routing module.
Here is good tutorial for this http://www.ng-newsletter.com/posts/angular-ui-router.html