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
Related
Please see my plunkr here
https://plnkr.co/edit/hk7Z0jMwOfoUwJZ98F7a?p=preview
In my app.js I have two controllers and a routeprovider with a resolve for TestController
var app = angular.module('app', ['ngRoute']);
app.controller('DefaultController', ['$scope', function($scope){
$scope.welcome = "Hello World";
}]);
app.controller('TestController', ['$scope', 'context', '$routeParams', function($scope, context, $routeParams){
$scope.text = "TestController loaded!"
}]);
app.config(['$routeProvider', '$httpProvider', function($routeProvider, $httpProvider){
$routeProvider.
when('/test1',{
templateUrl: 'test1.html',
controller: 'TestController',
resolve: {
context: function(){return 'test';}
}
})
}])
In my html, I have an ng-include which should also load test.html in the default view
<body ng-controller="DefaultController">
<h1>{{welcome}}</h1>
<div ng-include="'test.html'" ng-controller='TestController'></div>
</body>
I cannot take the resolve out of the routeProvider as I still need it to when the user goes to '../test'
Is there any way I can resolve contextProvider from the ng-include?
or is there better ways to do this?
Any help would be greatly appreciated.
Create a factory/service and use that:
app.factory('fooResolver', function() {
return {
resolveMe: function() {
return 'test';
}
}
});
Now, use this in your router config:
app.config(['$routeProvider', '$httpProvider', function($routeProvider, $httpProvider){
$routeProvider.
when('/test1',{
templateUrl: 'test1.html',
controller: 'TestController',
resolve: {
context: function(fooResolver) {
return fooResolver.resolveMe();
}
}
})
}])
And do the same in your controller:
app.controller('TestController', ['$scope', 'fooResolver', '$routeParams', function($scope, fooResolver, $routeParams){
$scope.text = "TestController loaded!"
var context = fooResolver.resolveMe();
}]);
When I implemented in my code mechanism to change url's query in background (using $location.search), it caused disappearing all tooltips which have option tooltip-append-to-body, at the moment of changing url value. I need tooltip-append-to-body attribute because of another reasons (the simplest solution is to remove it but that's not the solution for me).
My code looks like this:
js:
angular.module('mapp', ['ui.router', 'ui.bootstrap'])
config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.when('', '/');
$stateProvider
.state('home', {
url: '/',
reloadOnSearch: false,
templateUrl: 'home.html'
});
}
])
.controller('myCtrl', ['$scope', '$timeout', '$location',function($scope, $timeout, $location) {
var value = 0;
var runTimeout = function() {
$timeout(function() {
$location.search('start', value++);
runTimeout();
}, 500);
};
runTimeout();
}]);
index.html:
<body ng-app="mapp" ng-controller="myCtrl" style="">
<ui-view></ui-view>
</body>
home.html:
tooltip
Here you have plunker: http://plnkr.co/edit/DkmcSMGmYAowbI4rNQ6W?p=preview.
I have an ApplicationController on the body tag. Inside this controller I am setting the username on a response from the server. Somehow the username variable is only available within the HomeController, which is currently not implemented.
index.html
<body ng-controller="ApplicationController">
Welcome {{username}}.
<div ng-view></div>
</body>
home.html
<div>You are logged in as {{username}}.</div>
Javascript
angular.module('APP', [
'ngRoute',
'APP.services',
'APP.controllers',
'APP.auth'
])
.config(function($routeProvider, $httpProvider) {
$httpProvider.interceptors.push('httpRequestInterceptor');
$routeProvider.when("/", {
templateUrl: "/static/partials/home.html",
controller: "HomeController"
});
return $routeProvider.otherwise({
redirectTo: "/"
});
}
);
angular.module("APP.controllers", ['ui.bootstrap.modal'])
.controller("HomeController", function($scope, $rootScope) {
})
.controller('ApplicationController', function($scope, $rootScope, USER_ROLES,
AUTH_EVENTS, AuthService, $modal,
UserService) {
$scope.username = null;
$scope.setCurrentUser = function(user) {
$scope.username = user.username;
}
$rootScope.$on(AUTH_EVENTS.loginSuccess, function(event) {
UserService.get().then($scope.setCurrentUser);
});
});
Generated output
<body>
Welcome
<div>You are logged in as AceUser</div>
</body>
Update 1
If I select the ApplicationController element and then run angular.element($0).scope() I can see the scope and the username available. But still it is not output in the document.
Update 2
The index.html was being generated with Django. Django was processing the template variable and not sending it as output. The solution was to wrap the variable with the {% verbatim %} tag. I will leave this up here for anyone who also has this problem.
Not quite sure why it works in the HomeController. I put together a working Plunk for you to compare your code with.
angular.module('APP', [
'ngRoute',
'APP.controllers'
])
.config(function($routeProvider, $httpProvider) {
$routeProvider.when("/", {
templateUrl: "home.html",
controller: "HomeController"
});
return $routeProvider.otherwise({
redirectTo: "/"
});
});
angular.module("APP.controllers", [])
.controller("HomeController", function($scope, $rootScope) {})
.controller('ApplicationController', function($scope, $rootScope) {
$scope.username = null;
$scope.setCurrentUser = function(user) {
$scope.username = user.username;
}
$scope.setCurrentUser({username: 'bob'});
});
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.
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.