$routeParams not populating - javascript

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;

Related

module dependency with ngRoute breaks angular rendering

I am trying to use Mean stack in my website project. I am using ngRoute for routing and I want to add bootstrap carousel to my main page. I am trying to put angular team carousel component from this page.
While I am trying to implement this, I realize as soon as I try to add module dependency ( which is var app = angular.module('myApp', []) ) to my controller , angular breaks (without any error) and nothing appear in page. If I delete, everything is working normal. I assume this is related with routing ?
Project Structure;
-myApp
-node_modules
package.json
server.js
-public
-controllers
-lib
-views
app.js
index.html
app.js ;
(function(){
var app = angular.module('filmSevmem', ['ngRoute']);
app.config(function($routeProvider){
$routeProvider
.when('/main', {
templateUrl: 'views/main.html',
controller: 'MainController'
})
.when('/about', {
templateUrl: 'views/about.html',
controller: 'AboutController'
})
.when('/contact', {
templateUrl: 'views/contact.html',
controller: 'ContactController'
})
.otherwise({redirectTo:'/main'});
});
})();
MainController.js;
(function(){
var app = angular.module('myApp');
var MainController = function ($scope, $http) {
....... // codes from carousel
.......
app.controller('MainController', MainController);
})();
If I add , [] or ['ngAnimate', 'ui.bootstrap'] or anything to right of 'myApp', nothing work and I get empty page from my localhost. What can cause this problem ? What should I do ? Thank you.
var app = angular.module('myApp'); means get me the module myApp.var app = angular.module('myApp', [listOfDependencies]); means create the module myApp with all of the listed dependencies. So if you put square brackets in app.js AND in mainController.js, then you overwrite the previously created. The simplest solution would be to add ngAnimate and ui.bootstrap in your app.js like this: var app = angular.module('myApp', ['ngRoute','ngAnimate','ui.bootstrap']);
If you don't want to have all your dependencies in your root module, you can make submodules like var controllers = angular.module('myApp.controllers', ['ngAnimate']), and include this in your app.js like var app = angular.module('myApp', ['myApp.controllers']);
Why you are creating two different modules? And even you are not injecting the first module while creating the second.
By no chance your application is gonna work until and unless you code everything using single module or inject one module in another!

Angularjs Error: $injector:unpr Unknown Provider with using ui-router

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.

resolve not running before entering route

this is a jsbin showing the problem, however, I will explain it here. I am trying to use resolve to run some code before entering a route, however, it doesn't run (as the console.log statement provides more detail about). (Since it doesn't run, I'm not sure if I'm setting what would be the return value from resolve in the template correctly). Why isn't resolve running?
var app = angular.module('jsbin', ['ngRoute'])
.config(function ($routeProvider) {
'use strict';
console.log("this runs");
var routeConfig = {
controller: 'DemoCtrll',
resolve: {
store: function (demoStorage) {
console.log("this doesn't log");
return demoStorage;
}
}
};
$routeProvider
.when('/', routeConfig)
.otherwise({
redirectTo: '/'
});
});
app.controller('DemoCtrl', function($scope, $routeParams, store) {
this.name = store;
});
app.factory('demoStorage', function () {
'use strict';
return "World";
});
html
<body ng-app="jsbin">
<div ng-controller="DemoCtrl as demo">
<h1>Hello {{name}}</h1>
</div>
Some changes you would need:
You cannot use ng-controller directive along with ng-view's route bound controller, i.e set controller alias in the controller property of the route config controller: 'DemoCtrl as demo',.
When you use ng-controller directive to instantiate the controller it does not know what is store provider, because no such provider/service exists. It is a special dependency injected by the angular router and only the router knows how to inject store as dependency in your controller. That is the reason for the error when you used ng-controller.
You need to define a template html or a template and bind it to templateUrl property on the routeConfig. i.e templateUrl:'demo.html',
Remove ng-controller from the view.
You need to use ng-view directive to render the view. i.e in your index.html <ng-view></ng-view>
Since you are using controller alias you would refer to the property as demo.name in the view rendered by the route.
You also had a typo in the controller name #DemoCtrl1.
Overall it will look like this.
Define your template in say Demo.html (In the demo example i have used the convenient script type="text/ng-template")
<div>
<h1>Hello {{demo.name}}</h1>
</div>
Set the routeConfig:
var routeConfig = {
templateUrl:'demo.html',
controller: 'DemoCtrl as demo',
resolve: {
store: function (demoStorage) {
console.log("this doesn't log");
return demoStorage;
}
}
};
JSBin
Also see this answer though it uses angular ui-router, but the concept is the same.

Angular controller is not instantiated after minification

My original source code looks like this:
(function(angular) {
'use strict';
/* #ngInject */
function config($stateProvider) {
$stateProvider
.state('bar.foo', {
url: '/foo',
templateUrl: 'foo-view.html',
controller: 'FooController',
controllerAs: 'vm'
});
}
/* #ngInject */
function FooController() {
window.alert('foo');
}
angular
.module('my.foo', [])
.config(config)
.controller('FooController', FooController);
}(angular));
It works fine this way.
Then I minify it using ngAnnotate and UglifyJS, and get this code (formatted to easier reading):
function (a) {
'use strict';
function b(a) {
a.state('bar.foo', {
url: '/foo',
templateUrl: 'foo-view.html',
controller: 'FooController',
controllerAs: 'vm'
})
}
function c() {
window.alert('foo')
}
b.$inject = ['$stateProvider'],
a.module('my.foo', [])
.config(b)
.controller('FooController', c)
}(angular),
And, it does not work. When I go to the state bar.foo the controller do not get called. Others controllers and router states works fine. This one seems to get muted, the code inside the controller function is not called.
The console do not show any errors.
I do not know what to do or where to look at.
The entire JavaScript is bigger and is a concatenation of several small files. The single minified JS file has controllers before and after this one that works fine.
Debugging the minified file shows that the JavaScript is issuing the module definition calls to AngularJS, so the module, config and controller methods of Angular are called.
What should I search or check in the code? Am I missing something?
My problem was that I'm also compiling Jade templates into HTML. And my build settings for production environment is a little different than for development. Jade were outputting <div ui-view="ui-view"> instead of an empty attribute, preventing the ui-router to load the template into the parent view, causing the controller to not being instantiated.
The minification of the JavaScript was not the problem. Sorry.
These questions helped me out:
ui-router nested route controller isn't being called
Grunt jade compiler filling out empty attributes

How to split AngularJS application into smaller modules and handle routing correctly?

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

Categories

Resources