So I am trying to render a subview within a template but I want to define the state inside of the subviews controller on click of an element. The reason for splitting it out from the main controller is that I will be having subviews within the initial subview.
However, I get the following error:
Error: [$injector:modulerr] Failed to instantiate module
ivy.quote.controllers.durationCtrl due to: TypeError: Cannot read
property 'navigable' of undefined
This happens before I have even clicked the button which basically does the following
$state.transitionTo('quote.duration');
quote.tpl.html
<div class="quote grid" disable-scroll>
<div modal-from-bottom modal-hidden="calendarHide"
modal-content-class="quote__keypad" modal-speed="200" ui-view></div>
</div>
quoteCtrl.js
angular.module('ivy.quote.controllers.quoteCtrl', [
'ivy.quote.controllers.keypadCtrl',
'ivy.quote.controllers.durationCtrl',
'ivy.quote.services.quoteManager',
'ui.router',
'ivy.quote.calendar',
'wn.keypad',
'wn.gesture.disableScroll'
])
/**
* Configure UI Router
*/
.config(['$stateProvider', function ($stateProvider) {
$stateProvider.state('quote', {
url: '/quote',
controller: 'quoteCtrl',
templateUrl: 'quote/templates/quote.tpl.html'
});
}])
.controller('quoteCtrl', ['$scope', '$timeout', '$state', 'quoteManager',
function ($scope, $timeout, $state, quoteManager) {
}]);
duration.tpl.html
<div class="quote__calendar">
<h2>DURATION</h2>
<div ui-view></div>
</div>
durationCtrl.js
angular.module('ivy.quote.controllers.durationCtrl', [
'ui.router'
])
.config(['$stateProvider', function ($stateProvider) {
$stateProvider.state('quote.duration', {
url: '/duration',
controler: 'durationCtrl',
templateUrl: 'quote/templates/duration.tpl.html'
});
}])
.controller('durationCtrl', ['$scope', function ($scope) {
console.log('durationCtrl', $scope);
}]);
Your controller should be spelled "controller", not "controler", but otherwise, this looks like all the tutorials I've seen on subviews.
Related
This question already has answers here:
What are the nuances of scope prototypal / prototypical inheritance in AngularJS?
(3 answers)
Closed 2 years ago.
I have my front part of the application in AngularJs with JSP files.
The index.jsp use the directive ng-view to show the views :
index.jsp
<div ng-view autoscroll="true" style="overflow: auto;"></div>
and the app.js to link with $routeProvider the controller to the view (home.jsp do some includes of views.jsp) :
app.js
$routeProvider
.when('/Error', {
controller: 'LoginController',
templateUrl: 'modules/authentication/views/errorConnexion.jsp',
hideMenus: true
})
.when('/', {
controller: 'HomeController',
templateUrl: 'modules/home/views/home.jsp'
})
.otherwise({ redirectTo: '/login' });
and my HomeController uses fields to hide or show some DOM elements :
HomeController.js
app.controller('HomeController',
['$timeout',
'service',
'$scope',
'$rootScope',
'$filter',
'$location',
'$window',
'ModalService',
'ngTableParams',
'$http',
'$interval',
'Excel',
function($timeout, service, $scope,
$rootScope, $filter, $location, $window,
ModalService, ngTableParams, $http, $interval, Excel) {
$scope.Hide_Module = true;
})]);
My controller child :
ChildController.js
app
.controller('ChildController',
function() {
$scope.field = "random";
}
);
And finally the problem, the view :
view.jsp
<section ng-controller="ChildController" class="content"
ng-hide="Hide_Module">
The problem is : If I remove ng-controller directive on the section tag, all is alright.
But if I add it, the main view (index.jsp) shows view.jsp......
So I want to know what I did wrong and moreover how angularjs deals with controllers inheritance and how they are binded through the views ?
Find out by myself, here two errors in my project :
Link to the controller file missing
<script src="modules/controllers/sub/childController.js"></script>
(Added in the index.jsp)
Data shared through $scope variable only in Object syntax
Define $scope.myObject = { key: value, ... } in the parent controller instead of primitives and arrays.
Add the $scope argument in the child controller as :
app.controller('ChildController', ['$scope', function($scope) { } ]);
I have a problem with adding a Angular controller to my HTML view. The angular way of doing this is: ng-controller="<controller>". But because I am using RequireJs I have to do this in a different way. I have to add a sub page to every controller and view:
define(['app', 'login/LoginController'], function (app, LoginController) {
app.config(function ($routeProvider, $locationProvider) {
$routeProvider.when('/', {
templateUrl: "modules/" + 'login/login.html',
controller: LoginController
});
});
app.controller('LoginController', LoginController);
});
This way I can define my where my controller is and where my view is.
Problem
Now I have a header.html in which I want to include a menu.html. this can be done via: ng-include="'modules/menu/menu.html'". This works fine. But how can I add a controller to this menu.html?
I have tried: ng-controller="MenuController" but then I get the error: 'Error: [ng:areq] Argument 'MenuController' is not a function, got undefined'. So I do not know how I should add a controller to my menu.html with RequireJS.
MenuController
my MenuController looks as follows:
define(['$'], function ($) {
'use strict';
var MenuController = function ($location, menu, $scope) {
$scope.info="testing123";
};
return MenuController;
});
Anyone knows how I should do this?
You can for example use multiple views in the same controllerwith $stateProvider:
app.config(function ($stateProvider, $locationProvider) {
$stateProvider
.state('login', {
url: '/',
views: {
'menu': {
templateUrl: 'modules/menu/menu.html',
controller: MenuController
},
'login': {
templateUrl: 'modules/login/login.html'
controller: LoginController
}
}
});
});
Then in your template to call them you just need to do something like:
<div ui-view="menu"></div>
<div ui-view="login"></div>
You can see more info on github ui-router.
I have markup that has the following and then I have different sections of the app defined in different files. The problem I am running into is that the controllers that are on the main app page on load causes each of the nested controllers to run more than once. Any states that I change to with a click of the button are fine but these fire off 2-3 times each.
<html ng-app="myApp">
<body ng-controller="myController">
<div ng-controller="dashController">
<div ng-controller="listController">
</div>
</div>
</body>
</html>
My App.js
var myApp = angular.module('myApp', [
'user.profile',
'myApp.controllers',
'myApp.directives',
'ngCookies',
'ngAutocomplete',
'ui.router'
]).config(function($stateProvider, $urlRouterProvider, $locationProvider, $interpolateProvider) {
$interpolateProvider.startSymbol('{[{').endSymbol('}]}');
$urlRouterProvider.otherwise('/');
$stateProvider.
state('app', {
url: '/app',
templateUrl: '/views/homepage',
controller: 'MyCtrl1'
});
$locationProvider.html5Mode(true);
});
myApp.controllers
angular.module('myApp.controllers', ['ui.router','ngCookies']).
controller('myController', function ($scope, $http,$cookies) {
$scope.message = 'nothing to see here, move along';
if ($cookies.userdata) {
$cookies.userdata = $cookies.userdata.replace("j:", "");
console.log($cookies);
}
});
user.profile.js
angular.module('user.profile', [
'user.controllers',
'ngAnimate',
'ngCookies',
'ngResource',
'ngSanitize',
'nouislider',
'ui.router',
'ui.bootstrap',
'ngLinkedIn'
])
.config(function($stateProvider, $urlRouterProvider, $locationProvider,$interpolateProvider, $linkedInProvider) {
$interpolateProvider.startSymbol('{[{').endSymbol('}]}');
$linkedInProvider.set('appKey', '753pos06f998t3')
.set('scope', 'r_fullprofile');
//.set('authorize', true);
$locationProvider.html5Mode(true);
$stateProvider
.state('userDashboard', {
controller: 'dashController'
})
.state('userList', {
views : {
'popup' : {templateUrl: '/views/app/user/list/userList'}
},
controller: 'listController'
});
});
user.controllers.js
angular.module('user.controllers', ['ui.router', 'ngAutocomplete', 'nouislider', 'ui.bootstrap', 'ngCookies', 'ngLinkedIn', 'angularFileUpload','cgPrompt'])
.directive('onLastRepeat', function () {
return function (scope, element, attrs) {
if (scope.$last) setTimeout(function () {
scope.$emit('onRepeatLast', element, attrs);
}, 1);
};
}).
controller('dashController', function ($scope, $state, $modal, $log, $http, $cookies) {
$scope.user = [];
}).
controller('listController', function ($scope, $http, $cookies) {
});
My app also doesn't initialize unless I run angular.bootstrap(document, ["myApp"]);
I don't think it is having the controller defined in the $stateProvider and the DOM... if I remove from the DOM none of the ng-clicks work even after the controller fires... also I have an ng-click that changes the state and it's controller is defined in the stateProvider and in the DOM and it does not fire twice... what is does is kick off the two other controllers again first before proceeding with it's action though.
The issue is that you are defining your controllers with the routeProvider / stateProvider ie:
$stateProvider.state('userDashboard', {
controller: 'dashController'
})
.state('userList', {
views : {
'popup' : {templateUrl: '/views/app/user/list/userList'}
},
controller: 'listController'
});
an you are redifining them in the DOM using
<div ng-controller="dashController">
remove one or the other but don't use the two at the same time, I'd suggest to remove the one declared in the DOM, ng-controller="dashController"
cheers
I'm having issues using oclazyload with $stateProvider.
I have specified that the controller .js should be loaded in the router config, and it does,' but it's not available to use as an ng-controller attribute in the file loaded in templateURL.
ui-route config:
core
.run(
[ '$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}
]
)
.config(
[ '$stateProvider', '$urlRouterProvider',
function ($stateProvider, $urlRouterProvider) {
console.info('Routing ...');
$urlRouterProvider
.otherwise('/app/dashboard');
$stateProvider
.state('app', {
abstract: true,
url: '/app',
templateUrl: 'templates/app.html',
})
.state('app.orders', {
abstract: true,
url: '/orders',
templateUrl: 'templates/orders/orders.html',
})
.state('app.orders.index', {
url: '/index',
templateUrl: 'templates/orders/index.html',
resolve: {
deps: ['$ocLazyLoad',
function( $ocLazyLoad ){
console.info('Path ot order controller in route config',Momento.paths.js + 'controllers/orders/index.js');
return $ocLazyLoad.load([
Momento.paths.js + 'controllers/orders/index.js'
])
}
]
}
})
}
]
)
;
And my templateURL file starts:
<div class="" id="" ng-controller="OrdersIndexController">...</div>
But when it loads, console throws the error:
<info>orders/index controller loaded controllers/orders/index.js:3
<info>Now I've finished loading the controller/order/index.js config/ui-router.js:69
<info>orders template loaded VM30437:1 (<-- this is the app.orders abstract template with ui-view directive ready for app.orders.index view)
<error>Error: [ng:areq] Argument 'OrdersIndexController' is not a function, got undefined
... <trace>
So the file is loaded correctly by lazyload, confirmed by console output above and network tab in developer tools, but it's not available in the templateURL to use as controller? Does it need to be aliased either in router config using controller:'' key or in template? Does it need to be specifically attached to the (only) module in this app?
What am I missing?
PS: confirming that the name of the controller is in fact OrdersIndexController:
core
.controller('OrdersIndexController', [
'Model', '$scope', '$window',
function( Model, $scope, $window){
console.info("OrdersIndexController fired");
}
]);
You have to register your controller with
angular.module("myApp").controller
Working
angular.module("myApp").controller('HomePageController', ['$scope', function ($scope) {
console.log("HomePageController loaded");
}]);
Not working
var myApp = angular.module("myApp")
myApp.controller('HomePageController', ['$scope', function ($scope) {
console.log("HomePageController loaded");
}]);
Inside the function function($ocLazyLoad){} you must to declare the name of module that contains the controller and the name of file "to lazy load"
function( $ocLazyLoad ){
return $ocLazyLoad.load(
{
name: 'module.name',
files: ['files']
}
);
}
If you use the current documented way for ocLazyLoad 1.0 -> With your router
...
resolve: { // Any property in resolve should return a promise and is executed before the view is loaded
loadMyCtrl: ['$ocLazyLoad', function($ocLazyLoad) {
// you can lazy load files for an existing module
return $ocLazyLoad.load('js/AppCtrl.js');
}]
}
then in js/AppCtrl.js
You have something like this:
angular.module("myApp").controller('DynamicNew1Ctrl', ['$scope', function($scope) {
$scope.name = "Scoped variable";
console.log("Controller Initialized");
}]);
Note that with angular.module("myApp") you are attaching the new controller to an existing module, in this case the mainApp, so any of new dynamic controllers can use the app dependencies.
but you can define a new module an inject your dependencies, as described here, the later is used commonly when you estructure your app with a plugin architecture and you want to isolate the dynamic modules so they only have access to some especific dependencies
I am having a lot of trouble understanding how stateParams are supposed to work. Everywhere I look suggests that this should pass an item_id of 456 when I travel to the URL /#/manage/456, but instead $stateParams is an empty object. Furthermore, in the $state object that is passed to MainCtrl, I can access all of the parameters by using $state.params, however this seems to be undesirable and hackish.
angular
.module('router',['ui.router'])
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider)
{
$stateProvider
.state('manage',
{
url: '/manage',
templateUrl: '/templates/main.html',
controller: 'MainCtrl'
})
.state('manage.item_id',
{
url: '/:item_id',
templateUrl: '/templates/main.html',
controller: 'MainCtrl'
})
}])
.controller('MainCtrl', ['$scope', '$stateParams', '$state', function($scope, $stateParams, $state)
{
// empty object
console.log('$stateParams: ', $stateParams);
// shows the variables i want
console.log('$state.params: ', $state.params);
}])
What you're trying to do should work fine, see this JSFiddle: http://jsfiddle.net/ahchurch/gf7Fa/14/
<script type="text/ng-template" id="item.tpl.html">
embeded item template
</script>
<script type="text/ng-template" id="main.tpl.html">
<ul>
<li>change route</li>
</ul>
<div ui-view></div>
</script>
<div ui-view></div>
angular.module('myApp',['ui.router'])
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider)
{
$urlRouterProvider.otherwise("/manage");
$stateProvider
.state('manage',
{
url: '/manage',
templateUrl: 'main.tpl.html',
controller: 'MainCtrl'
})
.state('manage.item_id',
{
url: '/:item_id',
templateUrl:'item.tpl.html',
controller: 'MainCtrl'
})
}])
.controller('mainController', function(){})
.controller('MainCtrl', ['$scope', '$stateParams', '$state', function($scope, $stateParams, $state)
{
// empty object
console.log("main controller");
console.log($stateParams);
}]);
One thing I noticed is that your template is the same file for both states, so you may just be seeing the initialization of the "manage" state, and never seeing the "manage.item_id" state.