Reputation: 123
I have followed the documentation on the UI-Router site to the point that my code for configuring the $StateProvider is practically identical, but I cannot get my Components to load. I am able to see the html pages referenced in my templateUrl but the controllers are not being accessed. Also, when I provide a Controller reference in the state route it errors suggesting that the controller is not register
The first component on the index page:
<supply-chain-admin ng-cloak></supply-chain-admin>
(function () {
"use strict"
var module = angular.module("SCAdmin");
function AppController($timeout) {
var vm = this; // vm = ViewModel
vm.isNewBlankLoad = false;
vm.selectedMenuItem;
vm.changeMenu = true;
vm.$onInit = function () {
vm.changeMenu = true;
}
vm.collapseMainMenu = function (isCollapsed) {
vm.changeMenu = isCollapsed;
$timeout(function () { equalheight('.menuListItem'); }, 10);
};
}
module.component("supplyChainAdmin", {
templateUrl: "/Scripts/SupplyChainAdmin/SCAdminApp/SupplyChainAdmin.html",
bindings: {
},
controllerAs: "vm",
controller: ['$timeout', AppController]
});
})();
The inside this components html file:
<main-menu show-menu="vm.changeMenu"></main-menu>
<main-content show-menu="vm.changeMenu"></main-content>
Inside the main-menu component:
<div id="menuleft" ng-class="{hideMenu:!vm.showMenu,slide:vm.showMenu}">
<div id="mainMenuHeader">
<a class="pull-right" id="mainMenuToggleLink" ng-click="vm.toggleMenu()">
<img src="/Content/images/menu.png" />
</a>
</div>
<div id="mainMenu">
<ul class="menuList" ng-class="{hideMenu:vm.showMenu,slide:!vm.showMenu}"><!-- the :: symbol represents one time binding -->
<li title="{{ ::menuItem.ToolTip }}" class="menuListItem" ng-repeat="menuItem in vm.menuItems" ng-class="{ active: menuItem.Link == vm.selectedMenuItem }" resize-normal>
<button class="menuNotifications pull-right" ng-show="menuItem.Notification.length" popover="{{ ::menuItem.NotificationMessage }}" popover-trigger="focus" popover-placement="right" popover-append-to-body="true">{{ ::menuItem.Notification }}</button>
<a ng-click="vm.menuItemChanged(menuItem.Link)" ui-sref="{{ ::menuItem.Link }}">
<h1 ng-show="vm.showMenu"><span class="{{ ::menuItem.MenuIconClass }}"></span> {{ ::menuItem.Title }} <i class="line"></i></h1>
<p ng-hide="vm.showMenu"><span class="{{ ::menuItem.MenuIconClass }}"></span> <i class="line"></i></p>
<div class="menuItemContent" ng-class="{hide:!vm.showMenu}">
<ul class="list-unstyled list-inline">
<li ng-repeat="pointItem in menuItem.MenuItemPoints">
<div class="fa large-glyphicon {{ ::pointItem.IconClass }}" aria-hidden="true"></div>
<div class="menuSubItemText"> {{ ::pointItem.DisplayText }} </div>
<div class="menuSubItemValue"> {{ ::pointItem.DisplayValue }} </div>
</li>
</ul>
</div>
</a>
</li>
</ul>
</div>
(function () {
"use strict"
var module = angular.module("SCAdmin");
module.component("mainMenu", {
templateUrl: "/Scripts/SupplyChainAdmin/MainMenu/MainMenu.html",
bindings: {
showMenu: "="
},
controllerAs: "vm",
controller: ["$http", '$timeout', '$state', mainMenuController]
});
function mainMenuController($http, $timeout, $state) {
var vm = this; // vm = ViewModel
vm.isNewBlankLoad = false;
vm.menuItems = [];
vm.selectedMenuItem;
vm.$onInit = function () {
fetchMenuItems($http, $state).then(function (data) {
if (data.length) {
for (var i = 0, l = data.length; i < l; i++) {
if (data[i].MenuItemType === 1) {
vm.menuItems.push({ Link: 'Items', ToolTip: 'Items', Title: 'My Items', MenuItemType: 1, Notification: data[i].Notification, NotificationMessage: data[i].NotificationMessage, MenuItemPoints: data[i].MenuItemPoints, MenuIconClass: 'fa fa-tags' });
}
if (data[i].MenuItemType === 2) {
vm.menuItems.push({ Link: 'Vendors', ToolTip: 'Vendor', Title: 'My Vendors', MenuItemType: 2, Notification: data[i].Notification, NotificationMessage: data[i].NotificationMessage, MenuItemPoints: data[i].MenuItemPoints, MenuIconClass: 'fa fa-id-card' });
}
if (data[i].MenuItemType === 3) {
vm.menuItems.push({ Link: 'Facilities', ToolTip: 'Facilities', Title: 'My Facilities', MenuItemType: 2, Notification: data[i].Notification, NotificationMessage: data[i].NotificationMessage, MenuItemPoints: data[i].MenuItemPoints, MenuIconClass: 'fa fa-university' });
}
if (data[i].MenuItemType === 4) {
vm.menuItems.push({ Link: 'Departments', ToolTip: 'Departments', Title: 'My Departments', MenuItemType: 2, Notification: data[i].Notification, NotificationMessage: data[i].NotificationMessage, MenuItemPoints: data[i].MenuItemPoints, MenuIconClass: 'fa fa-bed' });
}
if (data[i].MenuItemType === 5) {
vm.menuItems.push({ Link: 'Pars', ToolTip: 'Pars', Title: 'My PARs', MenuItemType: 2, Notification: data[i].Notification, NotificationMessage: data[i].NotificationMessage, MenuItemPoints: data[i].MenuItemPoints, MenuIconClass: 'fa fa-stethoscope' });
}
if (data[i].MenuItemType === 6) {
vm.menuItems.push({ Link: 'Maintenance', ToolTip: 'Maintenance', Title: 'Maintenance', MenuItemType: 2, Notification: data[i].Notification, NotificationMessage: data[i].NotificationMessage, MenuItemPoints: data[i].MenuItemPoints, MenuIconClass: 'fa fa-wrench' });
}
}
vm.selectedMenuItem = $state.current.name != null ? $state.current.name : vm.menuItems[0].ToolTip;
}
});
};
vm.menuItemChanged = function (selectMenuItem) {
vm.selectedMenuItem = selectMenuItem;
}
vm.menuItems = vm.menuItems;
vm.toggleMenu = function () {
vm.showMenu = (vm.showMenu) ? false : true;
$timeout(function () { equalheight('.menuListItem'); }, 10);
}
}
function fetchMenuItems($http) {
return $http.get(SupplyChainAdminUrl + 'Menu/GetMenuItems/', { params: { domain: CurrentUserDomain, userName: CurrentUserUserName } }).then(function (response) {
return response.data;
});
}
})();
Inside the main-content component:
<div id="contentFromMenu" ng-class="{hideMenu:vm.showMenu,slide:!vm.showMenu}">
<div class="overlay" ng-class="{show:vm.showMenu}" ng-click="vm.collapseMenu()"></div>
<div id="menuContentContainer">
<ui-view></ui-view>
</div>
(function () {
"use strict"
var module = angular.module("SCAdmin");
module.component("mainContent", {
templateUrl: "/Scripts/SupplyChainAdmin/MainContent/MainContent.html",
require: {
'parent': '^supplyChainAdmin'
},
bindings: {
showMenu: "<"
},
controllerAs: "vm",
controller: ["$http", '$timeout', mainContentController]
});
function mainContentController($timeout) {
var vm = this; // vm = Viewvm
vm.$onInit = function () {
}
vm.collapseMenu = function () {
//the parameter sets the show menu property to false;
vm.parent.collapseMainMenu(false);
};
};
})();
The router which is inside the app.js module file:
(function () {
"use strict";
var app = angular.module("SCAdmin", ['ui.router', 'ui.bootstrap', 'jQueryScrollbar', 'ngSanitize', 'angular.vertilize']);
app.config(function ($stateProvider, $urlMatcherFactoryProvider, $urlRouterProvider, $locationProvider) {
$urlRouterProvider.otherwise('/Items');
$urlMatcherFactoryProvider.caseInsensitive(true);
$locationProvider.html5Mode(true);
$urlRouterProvider.rule(function ($injector, $location, $window, $timeout) {
//We can write authorization / part access checks here.
//what this function returns will be set as the $location.url
var path = $location.path(), normalized = path.toLowerCase();
if (path != normalized) {
//alert(path);
//instead of returning a new url string, I'll just change the $location.path directly so I don't have to worry about constructing a new url string and so a new state change is not triggered
//$location.replace().path(normalized);
}
// because we've returned nothing, no state change occurs
});
$stateProvider
.state('Items', {
url: '/Items',
component: 'items',
templateUrl: '/Scripts/SupplyChainAdmin/Items/Items.html',
//onEnter: function(){
// alert('entering the Items state');
//}
})
.state('Vendors', {
url: '/Vendors',
component: 'Vendors',
templateUrl: '/Scripts/SupplyChainAdmin/Vendors/Vendors.html',
})
.state('Vendors.VendorList', {
url: '/List',
templateUrl: '/Scripts/SupplyChainAdmin/Vendors/List/VendorList.html'
})
.state('Facilities', {
url: '/Facilities',
component: 'facilities',
templateUrl: '/Scripts/SupplyChainAdmin/Facilities/Facilities.html',
})
.state('Departments', {
url: '/Departments',
component: 'departments',
templateUrl: '/Scripts/SupplyChainAdmin/Departments/Departments.html',
})
.state('Pars', {
url: '/Pars',
component: 'pars',
templateUrl: '/Scripts/SupplyChainAdmin/Pars/Pars.html',
})
.state('Maintenance', {
url: '/Maintenance',
component: 'maintenance',
templateUrl: '/Scripts/SupplyChainAdmin/Maintenance/Maintenance.html',
});
})
app.run(function ($rootScope, $timeout) {
$rootScope.$on('$stateNotFound', function (event, unfoundState, fromState, fromParams) {
event.preventDefault();
});
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams, options) {
$rootScope.stateIsLoading = true;
});
$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams, options) {
$timeout(function () { $rootScope.stateIsLoading = false; }, 300);
});
$rootScope.$on('$stateChangeError', function (event, toState, toParams, fromState, fromParams, error) {
event.preventDefault();
$timeout(function () { $rootScope.stateIsLoading = false; }, 300);
});
$rootScope.$on('$viewContentLoading', function (event, viewConfig) {
//$rootScope.stateIsLoading = true;
});
$rootScope.$on('$viewContentLoaded', function (event, viewConfig) {
//$rootScope.stateIsLoading = false;
});
})
}());
I am aware that the nested routes are not correctly configured. My focus is on the "Items" state for this post. The html loads, but the component does not.
Upvotes: 1
Views: 2315
Reputation: 832
Seems like problem is in your state definitions with components, for example:
.state('Vendors', {
url: '/Vendors',
component: 'Vendors',
templateUrl: '/Scripts/SupplyChainAdmin/Vendors/Vendors.html',
})
As of latest ui-router you need to specify routes with components providing route name, url, component and resolver(optionally)
$stateProvider.state({
name: 'Vendors',
url: '/Vendors',
component: 'Vendors'
});
You don't need to provide templateUrl in state definition as you've already set this inside your component's definition.
Also if you change URL but don't want to reload page you can supply additional state definition param reloadOnSearch : false
Like:
$stateProvider.state({
name: 'Vendors',
url: '/Vendors',
component: 'Vendors',
reloadOnSearch : false
});
Hope this helps.
Upvotes: -1