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.
Related
I am working with IONIC Framework (Angularjs)
I am receiving below error,
463788 error Error: [ng:areq] http://errors.angularjs.org/1.4.3/ng/areq?p0=PaymentCtrl&p1=not%20a%20function%2C%20got%20undefined
at Error (native)
at http://localhost:8100/lib/ionic/js/angular/angular.min.js:6:416
at Sb (http://localhost:8100/lib/ionic/js/angular/angular.min.js:22:18)
at Qa (http://localhost:8100/lib/ionic/js/angular/angular.min.js:22:105)
at http://localhost:8100/lib/ionic/js/angular/angular.min.js:79:497
at I.appendViewElement (http://localhost:8100/lib/ionic/js/ionic-angular.min.js:17:4463)
at Object.O.render (http://localhost:8100/lib/ionic/js/ionic-angular.min.js:16:17590)
at Object.O.init (http://localhost:8100/lib/ionic/js/ionic-angular.min.js:16:16825)
at I.render (http://localhost:8100/lib/ionic/js/ionic-angular.min.js:17:3419)
at I.register (http://localhost:8100/lib/ionic/js/ionic-angular.min.js:17:3150)
Here is my code for controller.
define(['ionic', 'ionicAngular', 'angular',
'ngRoute', 'angularAnimate', 'angularSanitize', 'uiRouter'],
function (ionic, ionicAngular, angular) {
'use strict';
console.log('Payment controller ');
var PaymentCtrl = function ($scope, PaymentSvc,$state, $ionicLoading) {
/*$scope.phoneNumberVerification = function() { $state,$ionicPopup,
console.log('PhoneNumber controller added1 ');
$ionicLoading.hide();
$state.go('tab.eateries');
};*/
// When button is clicked, the popup will be shown...
};
return PaymentCtrl;
});
Serveics.js
define(['ionic', 'ionicAngular', 'angular',
'ngRoute', 'angularAnimate', 'angularSanitize', 'uiRouter'],
function (ionic, ionicAngular, angular) {
'use strict';
//console.log('service modules');
var PaymentSvc = function(){
console.log('serverices call');//var svc = this;
}
return PaymentSvc;
});
// });*/
payment.js
define(['ionic', 'ionicAngular', 'angular',
'./modules/payment/controllers/paymentctrl',
'./modules/payment/services/services',
'ngRoute', 'angularAnimate', 'angularSanitize', 'uiRouter'],
function (ionic, ionicAngular, angular,
paymentCtrl,
paymentSvc) {
'use strict';
console.log('payment.js modules');
var payment = angular.module('payment', ['ionic'])
.controller('PaymentCtrl', paymentCtrl)
.service('PaymentSvc',paymentSvc);
return payment;
});
No need to inject ['angular','ngRoute', 'angularAnimate', 'angularSanitize', 'uiRouter']. Ionic automatically inject angular decencies when you inject ['ionic']
Just write your controller directly
angular.module('starter', ['ionic']).controller('PayCtrl',function ($scope,$state,$ionicLoading,PaymentSvc){
//starter is the app name come from ng-app="starter"
$ionicLoading.show();
$scope.phoneNumberVerification = function(){
console.log('PhoneNumber controller added1');
$ionicLoading.hide();
$state.go('tab.eateries');
};
});
I advise you to organize your javascript project files to in 3 files:
app.js which contains
angular.module('starter', ['ionic', 'starter.controllers','starter.services'])..config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('app', {
url: '/app',
abstract: true,
templateUrl: 'templates/menu.html',
controller: 'AppCtrl'
}).state('app.home', {
url: '/home',
views: {
'tab-home': {
templateUrl: 'templates/home.html',
controller : 'HomeCtrl'
}
}
});
$urlRouterProvider.otherwise('/app/home');
});
controller.js which contains your controllers
angular.module('starter.controllers', []).controller('AppCtrl', function('PayCtrl',function ($scope,$state,$ionicLoading,PaymentSvc){
$ionicLoading.show();
$scope.phoneNumberVerification = function(){
console.log('PhoneNumber controller added1');
$ionicLoading.hide();
$state.go('tab.eateries');
};
});
service.js which contains you connections to server
angular.module('starter.services', []).factory('PaymentSvc',function($http,$q){
});
it is an injection error. for example, if you inject ['a','b','c'] you must have it in your function in the same order and amount: function(a,b,c). in your case, you have more parameters in the injection than the parameters in your controller function.
I have following setup for my project. Everything works fine.
In my Index.html I have two links (two $state). If I click on one of them, appropriate controller gets initiated dynamically as required. So dynamic concept works fine. But look at my index.html page below,
Index.html
<script src="~/Scripts/require.js" data-main="ANGULAR/main.js"></script>
<div data-ng-controller="appCtrl"> // only this line is not working and throwing an error saying appCtrl is not a function...
// Everything works fine. There is no problem at all. But look at the above line (data-ng-controller="appCtrl"). I know how can I initiate controller dynamically this way?
// When this line gets initiated it throws an error stating that appCtrl is not a function. I really don't know how to initiate appCtrl with this following setup.
<a ui-sref="dashboard">DASHBOARD</a><br /> //works fine
<a ui-sref="login">LOGIN</a> //works fine
<ui-view></ui-view> //works fine
</div>
main.js
require.config({
paths: {
"angular": "//localhost:59293/Scripts/angular",
"ui-router": "//localhost:59293/Scripts/angular-ui-router",
"ui-bootstrap": "//localhost:59293/Scripts/angular-ui/ui-bootstrap-tpls",
// "appCtrl":"//localhost:59293/ANGULAR/APP/appCtrl"
},
shim: {
"angular": {
exports: 'angular'
},
"ui-router": {
deps: ['angular']
},
"ui-bootstrap": {
deps: ['angular']
},
// "appCtrl": {
// deps: ['angular']
// }
}
});
define(
['angular',
'APP/app',
'APP/appCtrl' // Should I write this here ????????????????
], function (angluar, app) {
angular.bootstrap(document, ['MyApp'])
});
app.js looks like this,
define([
'angular',
'ui-router',
'ui-bootstrap',
], function (angular) {
var app = angular.module('MyApp', ['ui.router', 'ui.bootstrap']);
function lazy() {
var self = this;
this.resolve = function (controller) {
return {
ctrl: ['$q', function ($q) {
var defer = $q.defer();
require(['controllers/' + controller], function (ctrl) {
app.register.controller(controller, ctrl);
defer.resolve();
});
return defer.promise;
}]
};
};
this.$get = function () {
return self;
};
}
function config($stateProvider, $urlRouterProvider,
$controllerProvider, $compileProvider,
$filterProvider, $provide, lazyProvider) {
$urlRouterProvider.otherwise('/dashboard');
$stateProvider
.state("dashboard", {
url: "/dashboard",
controller: 'Dashboard/dashboardCtrl', // this works fine
controllerAs: 'vm',
templateUrl: 'ANGULAR/TEMPLATES/DASHBOARD/dashboard.html',
resolve: lazyProvider.resolve('Dashboard/dashboardCtrl')
})
.state("login", {
url: "/login",
controller: 'loginCtrl', //this works fine
controllerAs: 'vm',
templateUrl: 'ANGULAR/TEMPLATES/Login.html',
resolve: lazyProvider.resolve('loginCtrl')
})
;
app.register = {
controller: $controllerProvider.register,
directive: $compileProvider.directive,
filter: $filterProvider.register,
factory: $provide.factory,
service: $provide.service,
constant: $provide.constant
};
}
app.provider('lazy', lazy);
app.config(config);
return app;
});
appCtrl.js // I want this to work correctly.
//This controller doesn't get called with data-ng-controller attribute :(
// how and where should I add appCtrl.js reference as it is not defined in route config function? in main.js? if Yes, then how?
// I have commented code in main.js. please help and suggest.
define([
], function () {
console.log('appCtrl controller loaded');
ctrl.$inject = ['$http','$scope'];
function ctrl($http,$scope) {
this.message = '-- from a lazy controller.';
debugger;
$scope.myVar= "hello world"; // I want this value in HTML page.
};
return ctrl;
});
Please look at http://plnkr.co/edit/UDqaD7QKvgqtzgttXLHq?p=preview
but this is not working as mentioned... I just want to initiate appCtrl.js with ng-controller attribute dyanmically.
First, I've never seen a controller written like that. So that might be one of your problems. Another problem I see is that you are not declaring your controllers. Here's a plunker http://plnkr.co/edit/f343W3?p=preview
But here's the code. First, in your app.js
var app = angular.module('MyApp', [
'ui.router',
// Add your controller
'MyApp.controllers.appCtrl'
]);
Otherwise it angular won't know what you mean.
Second, your controller:
(function (){
'use strict';
function appCtrl(){
var vm = this;
vm.appVar = "Hi from appCtrl";
}
angular.module('MyApp.controllers.appCtrl', [])
.controller('appCtrl', appCtrl);
})();
Done like that, and angular should have no troubles finding your controllers.
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
Having created a very basic prototype AngularJS project, I wanted to migrate it to use RequireJS to load the modules. I modified my app based on the AngularAMD and AngularAMD-sample projects.
Now, when I access my default route I get:
Uncaught TypeError: Cannot read property 'directive' of undefined
I've been scratching my head as to why the dependency on 'app' is not being satisfied. If anyone can spot what I'm obviously doing wrong, it'd be much appreciated.
I've put the source code of my project here on GitHub, but here's the key parts:
main.js
require.config({
baseUrl: "js/",
// alias libraries paths
paths: {
'angular': '../bower_components/angular/angular',
'angular-route': '../bower_components/angular-route/angular-route',
'angular-resource': '../bower_components/angular-resource/angular-resource',
'angularAMD': '../bower_components/angularAMD/angularAMD',
'ngload': '../bower_components/angularAMD/ngload',
'jquery': '../bower_components/jquery/jquery'
},
// Add angular modules that does not support AMD out of the box, put it in a shim
shim: {
'angularAMD': ['angular'],
'ngload': [ 'angularAMD' ],
'angular-route': ['angular'],
'angular-resource': ['angular']
},
// kick start application
deps: ['app']
});
app.js
define(['angularAMD', 'angular-route', 'controller/login', 'controller/project_detail', 'controller/project_list'], function (angularAMD) {
'use strict';
var app = angular.module('cmsApp', ['ngRoute']);
app.constant('REMOTE_BASE_URL', "/cms/v2/remote");
app.constant('SERVER_ERROR_TYPES', {
authentication: 'Authentication',
application: 'Application',
transport: 'Transport'
});
app.constant('AUTH_ERROR_TYPES', {
invalidLogin: "INVALID_CREDENTIALS",
invalidToken: "INVALID_TOKEN",
noToken: "NO_TOKEN"
});
app.constant('AUTH_EVENTS', {
loginSuccess: 'auth-login-success',
loginFailed: 'auth-login-failed',
logoutSuccess: 'auth-logout-success',
notAuthenticated: 'auth-not-authenticated'
});
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/login', {
templateUrl: 'partials/login.html',
controller: 'LoginCtrl'
}).
when('/projects', {
templateUrl: 'partials/project-list.html',
controller: 'ProjectListCtrl'
}).
when('/projects/:projectId', {
templateUrl: 'partials/project-detail.html',
controller: 'ProjectDetailCtrl'
}).
otherwise({
redirectTo: '/projects'
});
}]);
return angularAMD.bootstrap(app);
});
And the file which the exception is being raised in:
login_form.js
define(['app'], function (app) {
app.directive('loginForm', function (AUTH_EVENTS) {
return {
restrict: 'A',
template: '<div ng-if="visible" ng-include="\'partials/login.html\'">',
link: function (scope) {
scope.visible = false;
scope.$on(AUTH_EVENTS.notAuthenticated, function () {
scope.visible = true;
});
scope.$on(AUTH_EVENTS.loginFailed, function () {
alert("An error occured while trying to login. Please try again.")
scope.visible = true;
});
scope.$on(AUTH_EVENTS.logoutSuccess, function () {
scope.visible = true;
});
}
};
});
});
You are loading 'controller/login' before the app itself was created.
Probably it is better to create a separate module like
define(['directive/login_form', 'service/authentication'], function () {
'use strict';
var loginModule = angular.module('loginModule', []);
loginModule.controller('LoginCtrl', ...
loginModule.directive('loginForm', ...
and then do something like
var app = angular.module('cmsApp', ['ngRoute', 'loginModule']);
Does that make sense?
UPDATE:
I am just thinking of another solution. Just remove 'controller/login' from your app define. Using angularAMD your controller should not be loaded anyway before you navigate to the specified url. Just remove it and your controller gets loaded on demand. That way, app will be defined! (Although I would still suggest to create multiple modules. It feels better to not have everything in the app module but have multiple modules for different responsibilities. Also much better for testing.)
angularAMD.route({
templateUrl: 'views/home.html',
controller: 'HomeController',
controllerUrl: 'scripts/controller'
})
Note the field controllerUrl.
Have a look here.
I went through this tutorial. Now I am attempting incorporate require
I found this explanation.
I am currently getting an error
Object #<Object> has no method 'unshift'
Here is the code that is causing the error
require(['jquery', 'angular', 'app/routes/app'], function ($, angular, mainRoutes) {
//tried this way as well
//$(function () { // using jQuery because it will run this even if DOM load already happened
// angular.bootstrap(document, ['mainApp']);
//});
require(['Scripts/app/modules/mainApp.js'], function (mainApp) {
angular.bootstrap(document.body, [mainApp]);//based of orginal answer
})
});
my app.js file
define(['app/modules/mainApp', 'app/controller/controllers'], function (mainApp) {
return mainApp.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/phones', {
templateUrl: 'Templates/phone-list.html',
controller: 'PhoneListCtrl'
}).
when('/phones/:phoneId', {
templateUrl: 'Templates/phone-detail.html',
controller: 'PhoneDetailCtrl'
}).
otherwise({
redirectTo: '/phones'
});
}]);
});
and my mainApp.js file
define(['angular', 'angular-resource'], function (angular) {
return angular.module('mainApp', ['ngResource']);
});
there are other files that I didnt show (controllers, services) but I dont think the problem lies their
UPDATE
I am now getting an error of undefined injector.
This is the only break point that gets hit, but the item is not undefined.
UPDATE 2
I updated my project to more resemble this
my main.js now is this
require.config({
baseUrl: '/Scripts/',
urlArgs: "bust=" + (new Date()).getTime(),
paths: {
'jquery': 'lib/require-jquery',
'angular': 'lib/angular/angular.min',
'angular-resource': 'lib/angular/angular-resource.min',
},
shim: {
'angular': { 'exports': 'angular' },
'angular-resource': { deps: ['angular'] },
'jQuery': { 'exports': 'jQuery' },
},
priority: [
'angular'
]
});
require(['angular', 'app/modules/app', 'app/routes/routes'], function (angular, app, routes) {
var $html = angular.element(document.getElementsByTagName('html')[0]);
angular.element().ready(function () { //breakpoint here
$html.addClass('ng-app');
angular.bootstrap($html, [app.name]);
});
});
if i put a break point on angular element and run a test in console
(app == routes)
true
should app be equal to routes?
The second argument of bootstrap method should be an array, I made the change on the code below.
require(['jquery', 'angular', 'app/routes/app'], function ($, angular, mainRoutes) {
//tried this way as well
//$(function () { // using jQuery because it will run this even if DOM load already happened
// angular.bootstrap(document, ['mainApp']);
//});
require(['Scripts/app/modules/mainApp.js'], function (mainApp) {
angular.bootstrap(document.body, [mainApp]);
})
});