Keeping controllers in different files not working in Angular - angularjs

I am currently defining my global module in my routes.js, but for some reason the other controllers are not being created and I keep getting errors that say that my main app module 'LiveAPP' is not available. Here is my code:
routes.js
angular.module('LiveAPP', ['ngRoute'])
.config(function($routeProvider, $httpProvider) {
$routeProvider
.when('/', {
templateUrl : '/home.html',
controller : 'mainCtrl'
})
.when('/signup',{
templateUrl : '/signup.html',
controller : 'signUpCtrl'
})
.when('/artist',{
templateUrl : '/artistpage.html',
controller : 'artistCtrl'
})
})
mainCtrl.js
angular.module('LiveAPP')
.controller('mainCtrl', ['$scope','$http', '$location',mainCtrl]);
function mainCtrl($scope,$http,$location){
$scope.somefunc = function(artistname){
dataFactory.ArtistfromSpotify()
.success(function(data, status, headers, config){
console.log(data)
})
}
};
signUpCtrl
angular.module('LiveAPP')
.controller('signUpCtrl', ['$scope','$http',signUpCtrl]);
function signUpCtrl($scope,$http){
$scope.user = {
email:'',
password:''
}
$scope.postreq = function(user){
$http({
method: "post",
url: "/signup",
data:{
user_username:user.email,
user_password:user.password
}
}).success(function(data){
console.log("User posted to the database")
});
};
}
artistCtrl
angular.module('LiveAPP')
.controller('artistCtrl', ['$scope',function($scope){
$scope.myRating =
{number:3}
}])
.directive("rateYo", function() {
return {
restrict: "A",
scope: {
rating: "="
},
template: "<div id='rateYo'></div>",
link: function( scope, ele, attrs ) {
console.log(scope.rating.number)
$(ele).rateYo({
rating: scope.rating.number
});
}
};
});
I was under the impression that I could retrieve the main liveAPP module and add controllers in other files by using angular.model('liveAPP').controller(...) For some reason it's not working. Anyone have any idea?

To elaborate on my comment above, when you re-use the same module across files, you need to load the files in the right order to satisfy dependencies as well as ensure the module is created before being used.
An easy way to avoid this problem is to specify one module per file. For example
mainCtrl.js
(function() {
angular.module('LiveAPP.main', [])
.controller('mainCtrl', ...);
})();
and in your routes.js
(function() {
angular.module('LiveAPP', [
'ngRoute',
'LiveAPP.main'
])
.config(function($routeProvider, $httpProvider) {
$routeProvider.when('/', {
templateUrl: '/home.html',
controller: 'mainCtrl'
})...
});
})();

It's likely that your html file is including the js files in the wrong order. You need to make sure that routes.js appears first in the html.

You need to change signUpCtrl.js to
angular.module('LiveAPP.controller', [])
.controller('signUpCtrl', ['$scope','$http',signUpCtrl]);
and inject LiveAPP.controller to your global module
angular.module('LiveAPP', ['ngRoute', 'LiveAPP.controller'])
You cannot have LiveAPP in more than one module. Make the same updates on all of your controllers and inject that module names in routes.js

Related

Using angular routeProvider with controller

Please consider the this code where the routeProvider is needed to inject page(n).html in ng-view.
In addition to the console error:
unknown provider: $routeProviderProvider <- $routeProvider
The argument to function routeIt is the name of the page to navigate to, How can I mix a conditional switch with routeProvider.when in order to call the page matching the argument in the most efficient manner? Thanks
(function () {
'use strict';
angular
.module('appModule')
.controller('MainMenuCtrl', ['$scope', '$http', 'TogglerFactory', '$routeProvider', MainMenuCtrl]);
function MainMenuCtrl($scope, $http, Toggler, routeProvider) {
$http.get('models/mainMenu.json').then(
function (response) {
$scope.menuItems = response.data;
},
function (error) {
alert("http error");
}
)
function routeIt (page) {
routeProvider
.when('/page1', {
url: "/page1",
templateUrl: 'views/page1.html',
controller: 'Page1Ctrl'
})
.when('/page2', {
url: "/page2",
templateUrl: 'views/page2.html',
controller: 'Page2Ctrl'
})
}
$scope.itemClicked = function (item){
Toggler.menuToggle();
routeIt(item);
}
}
})();
Service providers aren't available for injection in run phase (i.e. anywhere but provider services and config blocks). It is possible to make route provider injectable and configure it after config phase,
app.config(function ($provide, $routeProvider) {
$provide.value('$routeProvider', $routeProvider);
});
And controllers aren't the best places to implement any logic (e.g. route hot-plug).
Ok you're using your routeProvider wrong you need to configure your routes inside .config blocks
angular.module('myApp', [])
.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/page1', {
url: "/page1",
templateUrl: 'views/page1.html',
controller: 'Page1Ctrl'
}
})
If you want to change the url from your controller use $location.path('/page1'); inside your controller.

Angularjs's controller dependancy with requirejs?

I am using angular js with require js to make a single page template.
Everything is working accept one thing. When I am trying to define controller name in $routeProvider, it shows an error:
Error: [ng:areq] http://errors.angularjs.org/1.4.8/ng/areq?p0=SignIn&p1=not%20aNaNunction%2C%20got%20undefined
I separate the files like that:
rootfolder
js
-require.js
-angular.min.js
-angular-route.js
-main.js
-app.js
-signin.js
-signup.js
index.php
sign_in.php
sign_up.php
My code:
Main.js
require.config({
baseUrl: "./js",
paths: {
'angular': 'angular.min',
'angularRoute': 'angular-route'
},
shim: {
'angular' : { exports : 'angular' },
'angularRoute' : { deps : ['angular'] }
},
deps: ['app']
});
App.js
define(['angular','angularRoute'], function (angularRoute) {
var app = angular.module('webapp', ['ngRoute']);
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/signin', {
templateUrl: 'sign_in.php',
controller: 'SignIn'
}).
when('/signup', {
templateUrl: 'sign_up.php',
controller: 'SignUp'
}).
otherwise({
redirectTo: '/signin'
});
}
]);
return app;
});
controller - signin.js
define(['app'], function (app) {
app.controller('SignIn', function ($scope) {
$scope.message = "Sign in page";
});
});
controller - signup.js
define(['app'], function (app) {
app.controller('SignUp', function ($scope) {
$scope.message = "Sign up page";
});
});
When I define controller: 'SignIn' or controller: 'SignUp' in $routeProvider it shows an error otherwise it works fine.
You need to make requirejs include signin.js and signup.js, too. The code you have in App.js does not trigger any requirejs calls to load these two files.
when('/signin', {
templateUrl: 'sign_in.php',
controller: 'SignIn'
})
only tells AngularJS to try and instantiate the controller called 'SignIn' once you navigate to /signin. However, this will not result in the loading of the signin.js file.
Make sure to have your outer most module to depend on signin and signup, too.

AngularJS - How to separate controllers/modules?

I have one application that has two pages.
1 - A list of users
2 - Where I can manage a particular user
In order to organize I create two separated controllers and one module inside the app.js file and put all stuff together (custom filters, directives, factories...)
Now I want to separate things in diferent files (or maybe folders too).
How can I do this?
angular.module('app', []).
controller('listController', function ($scope) {
...
}).
controller('manageController', function ($scope) {
...
}).
factory('Api', ['$resource',
function($resource) {
return {
...
};
}]).
filter('formtaData', function(){
return function(data, modo){
...
}
}).
Other issue is that my controllers have different dependencies and in the actual way I have to include them all in my module (and scripts on the page) even if a page don't need them.
appConfig.js
angular.module('app', [dep1, dep2]);
ListController.js
angular.module('app').controller('listController', function ($scope) {
...
});
DetailsController.js
angular.module('app').controller('manageController', function ($scope) {
...
});
apiService.js
angular.module('app').factory('Api', ['$resource',
function($resource) {
return {
...
};
}]);
formatDataFilter.js
angular.module('app').filter('formtaData', function(){
return function(data, modo){
...
}
});
You can do it in this way
templates/
_login.html
_list.html
_manage.html
app/
app.js
controllers/
ListController.js
ManageController.js
directives/
SomeDirective.js
services/
ApiService.js
AnotherService.js
filters/
FormtaDataFilter.js
In app.js you can write something like this:
app.config(function($routeProvider){
$routeProvider
.when('/list', {
controller: 'ListController',
templateUrl: 'templates/_list.html'
})
.when('/manage', {
controller: 'ManageController.js',
templateUrl: 'templates/_manage.html'
})
.otherwise({redirectTo: '/'});
});
The above answer is correct however I usually assign the angular module to a literal to avoid typing the full name every time.
var angularApp = angular.module('app', [dep1,dep2]);

angular-ui-router: Load template from external resource ( express app )

Is it possible to load a template from a other application (like a express app) via $http?
Or from an other external source?
Not with ui-router alone, though the following lazy loading module for ui-router exists which may help you achieve your goal: ocLazyLoad - https://github.com/ocombe/ocLazyLoad
An example of how it works (taken from http://plnkr.co/edit/6CLDsz)
define([
'angular',
'uiRouter',
'ocLazyLoad',
'ocLazyLoad-uiRouterDecorator'
], function (angular) {
var app = angular.module('app', ['ui.router', 'oc.lazyLoad', 'oc.lazyLoad.uiRouterDecorator']);
app.config(function($stateProvider, $locationProvider, $ocLazyLoadProvider) {
$ocLazyLoadProvider.config({
loadedModules: ['app'],
asyncLoader: require
});
$stateProvider
.state('home', {
url: "/",
template: "<p>Hello {{name}}. Would you like to... <a href='#lazy'>load lazy</a>?</p>",
controller: 'mainCtrl'
})
.state('lazy', {
url: "/lazy",
lazyModule: 'app.lazy',
lazyFiles: 'lazy',
lazyTemplateUrl: 'lazy.html',
controller: 'lazyCtrl'
});
$locationProvider.html5Mode(true);
});
app.controller('mainCtrl', function($scope) {
$scope.name = 'World';
});
});
It is possible but you'll have to use a templateProvider. More clear explanation using an example:
$stateProvider.state('state', {
url: '/state',
//templateUrl: 'templates/stateTemplate.html',
templateProvider: function ($http, $templateCache) {
var tplUrl = 'http://another.accesible.domain/stateTemplate.html',
tpl = $templateCache.get(tplUrl);
return (!!tpl) ? tpl :
$http
.get(tplUrl)
.then(function (response) {
tpl = response.data
$templateCache.put(tplUrl, tpl);
return tpl;
});
},
controller: 'stateController as sCtrl',
params: {
target: null
},
resolve: {
loadCtrl: ['$ocLazyLoad', function ($ocLazyLoad) {
return $ocLazyLoad.load(['stateController', 'appDataProvider', 'appDataService', 'stateFactory', 'stateService']);
}],
resolveObject: function ($window) {
var result = $window.localStorage.getItem('resolveObj');
return result;
}
}
})
Hope it helps (late answer I know, but just found this question looking for something else). ocLazyLoad is needed if you don't want to load everything at once when your app starts, but load what is required when it's required. Quite useful if your app's memory footprint is an issue.
Best regards.

Using resolve in $routeProvider causes 'Unknown provider ...'

I am trying to do an asynchronous http request to load some data before my app loads and so I am using a resolve in $routeProvider which is an http request in my MainController. For some reason, I keep getting Error: [$injector:unpr] Unknown provider: appDataProvider <- appData where appData is where I do my http request. I am using AngularJS v 1.2.5.
Here is the code and two methods that I tried that both give the same error:
Method #1
MainController.js
var MainController = ['$scope','$location','appData',
function($scope, $location, appData){
console.log(appData.data);
}
];
MainController.loadData = {
appData: function($http, $location, MainFactory){
var aid = MainFactory.extractAid($location);
return $http({method: 'GET', url: URL_CONST + aid});
}
};
app.js
var app = angular.module('HAY', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/', {
redirectTo: '/pages/alerts'
})
.when('/pages/:pageName', {
templateUrl: function(params) {
return 'views/pages/' + params.pageName + '.html';
},
controller: MainController,
resolve: MainController.loadData
})
.otherwise({
redirectTo: '/pages/alerts'
});
});
I tried changing the name in case it was a conflicting system reserved keyword but with no luck. For some reason, appData is never recognized
Method #2
I also tried changing it around like so:
app.js
var app = angular.module('HEY', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/', {
redirectTo: '/pages/alerts'
})
.when('/pages/:pageName', {
templateUrl: function(params) {
return 'views/pages/' + params.pageName + '.html';
},
controller: MainController,
resolve: {
appData: ['$http', '$location','MainFactory', function($http, $location, MainFactory) {
var aid = MainFactory.extractAid($location);
return $http({method: 'GET', url: URL_CONST + aid});
}]
}
})
.otherwise({
redirectTo: '/pages/alerts'
});
});
MainController.js
var MainController = ['$scope','$location','appData',
function($scope, $location, appData){
console.log(resolvedData);
}
];
However, the result was exactly the same. Does this have something to do with angular 1.2.5 ?
Here is a working version from someone else
http://mhevery.github.io/angular-phonecat/app/#/phones
And here is the code:
function PhoneListCtrl($scope, phones) {
$scope.phones = phones;
$scope.orderProp = 'age';
}
PhoneListCtrl.resolve = {
phones: function(Phone) {
return Phone.query();
},
delay: function($q, $defer) {
var delay = $q.defer();
$defer(delay.resolve, 1000);
return delay.promise;
}
}
angular.module('phonecat', ['phonecatFilters', 'phonecatServices', 'phonecatDirectives']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/phones', {templateUrl: 'partials/phone-list.html', controller: PhoneListCtrl, resolve: PhoneListCtrl.resolve}).
otherwise({redirectTo: '/phones'});
}]);
Here's an example of the code I've used in the application I'm working on, not sure it will help much because its not much different than how you have it already.
Routing
.when('/view/proposal/:id',{
controller : 'viewProposalCtrl',
templateURL : 'tmpls/get/proposal/view',
resolve : viewProposalCtrl.resolveViewProposal
})
Controller
var viewProposalCtrl = angular.module('proposal.controllers')
.controller('viewProposalCtrl',['$scope','contacts','details','rationale',
function($scope,contacts,details,rationale){
$scope.contacts = contacts;
$scope.details = details;
$scope.rationale = rationale;
// [ REST OF CONTROLLER CODE ]
});
// proposalSrv is a factory service
viewProposalCtrl.resolveViewProposal = {
contacts : ['$route','proposalSrv',function($route,proposalSrv){
return proposalSrv.get('Contacts',$route.current.params.id)
.then(function(data){
return data.data.contacts;
},function(){
return [];
});
}],
details : ['$route','proposalSrv',function($route,proposalSrv){
return proposalSrv.get('Details',$route.current.params.id)
.then(function(data){
return data.data.details;
},function(){
return {};
});
}],
rationale : ['$route','proposalSrv',function($route,proposalSrv){
return proposalSrv.get('Rationale',$route.current.params.id)
.then(function(data){
return data.data.rationale;
},function(){
return {};
]
}]
};
Now that I think about it, when I was developing my application I did have a problem and not sure why when I named my resolve function "resolve." This gave me a problem:
.when('/path',{
// stuff here
resolve : myCtrlr.resolve
})
but this did not:
.when('/path',{
//stuff here
resolve : myCtrlr.myResolveFn
})
Another Possibility
The only other thing I can think of, is that you're returning the promise from the $http call and then trying to use appData.data Try using the .then function or one of the other functions (.success,.error) to retrieve the information from the promise.
The problem was NOT due to previously using different version of AngularJS.
Here are the fixes using the code that I have above.
In app.js, you need to declare the controller as controller: 'MainController' and NOT as controller: MainController even though you have var MainController = app.controller('MainController', ....).
Second and biggest thing was that in my index.html I declared my controller already like so:
index.html
body ng-app="HEY" controller="MainController" /body
This was causing the whole Unknown provider error Apparently angular wont tell you that you have already declared the controller that you are using to do the resolve it and that that will cause a weird error that have nothing to do with the resolve.
I hope this helps someone who may have the same problem.
One thing I noticed in angular 1x docs is that YOU DO NOT SPECIFY THE RESOLVED PARAMETER AS AN ANNOTATED DEPENDENCY
So this:
.when('/somewhere', {
template: '<some-component></some-component>',
resolve: {
resolvedFromRouter: () => someService.fetch()
}
})
export default [
'$scope',
'someService',
'resolvedFromRouter'
Controller
]
function Controller($scope, someService, resolvedFromRouter) {
// <= unknown provider "resolvedFromRouter"
}
is wrong. You don't specify the resolved parameter as a dependency, in the docs:
For easier access to the resolved dependencies from the template, the resolve map will be available on the scope of the route, under $resolve (by default) or a custom name specified by the resolveAs property (see below). This can be particularly useful, when working with components as route templates.
So just do this instead:
.when('/somewhere', {
template: '<some-component></some-component>',
resolve: {
resolvedFromRouter: () => someService.fetch()
}
})
export default [
'$scope',
'someService',
Controller
]
function Controller($scope, someService) {
$scope.$resolve.resolvedFromRouter; // <= injected here
}

Resources