diff --git a/.gitignore b/.gitignore index 703cf0cf0..de8839997 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,5 @@ node_modules npm-debug.log lib .bower + +.vscode \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js index 54fff0373..f11ee97e7 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -139,7 +139,8 @@ module.exports = function (grunt) { 'lib/angular-bootstrap/ui-bootstrap-tpls.js', 'misc/angular-bootstrap-prettify.js', 'lib/lodash/lodash.min.js', - 'dist/angular-patternfly.js'], + 'dist/angular-patternfly.js', + 'lib/angular-ui-router/release/angular-ui-router.min.js'], html5Mode: false, template: 'grunt-ngdocs-index.tmpl', styles: ['lib/patternfly/dist/css/patternfly.css', 'lib/patternfly/dist/css/patternfly-additions.css', diff --git a/bower.json b/bower.json index 21928db93..feb9df276 100644 --- a/bower.json +++ b/bower.json @@ -45,6 +45,7 @@ "patternfly": "~3.14.0" }, "devDependencies": { - "angular-mocks": "1.3.0 - 1.5.*" + "angular-mocks": "1.3.0 - 1.5.*", + "angular-ui-router": "^0.3.2" } } diff --git a/src/navigation/examples/vertical-navigation-basic.js b/src/navigation/examples/vertical-navigation-basic.js new file mode 100644 index 000000000..9bcd5c4d8 --- /dev/null +++ b/src/navigation/examples/vertical-navigation-basic.js @@ -0,0 +1,567 @@ +/** + * @ngdoc directive + * @name patternfly.navigation.directive:pfVerticalNavigation - Basic + * + * @description + * Directive for vertical navigation. This sets up the nav bar header with the collapse button (hamburger) and the + * application brand image (or text) as well as the vertical navigation bar containing the navigation items. This + * directive supports primary, secondary, and tertiary navigation with options to allow pinning of the secondary and + * tertiary navigation menus as well as the option for persistent secondary menus. + *

+ * The remaining parts of the navbar header can be transcluded. + *

+ * Tha navigation items are marked active based on the current location and the href value for the item. If not using + * href's on the items to navigate, set update-active-items-on-click to "true". + *

+ * This directive works in conjunction with the main content container if the 'container-pf-nav-pf-vertical' class + * selector is added to the main content container. + * + * @param {string} brandSrc src for brand image + * @param {string} brandAlt Text for product name when brand image is not available + * @param {boolean} showBadges Flag if badges are used on navigation items, default: false + * @param {boolean} persistentSecondary Flag to use persistent secondary menus, default: false + * @param {boolean} hiddenIcons Flag to not show icons on the primary menu, default: false + * @param {array} items List of navigation items + * + * @param {function} navigateCallback function(item) Callback method invoked on a navigation item click (one with no submenus) + * @param {function} itemClickCallback function(item) Callback method invoked on an item click + * @param {boolean} updateActiveItemsOnClick Flag if active items should be marked on click rather than on navigation change, default: false + * @param {boolean} ignoreMobile Flag if mobile state should be ignored (use only if absolutely necessary) default: false + * + * @example + + +
+ + + +
+ +
+ + angular.module('patternfly.navigation').controller('vertNavController', ['$scope', + function ($scope) { + $scope.navigationItems = [ + { + title: "Dashboard", + iconClass: "fa fa-dashboard", + href: "#/dashboard" + }, + { + title: "Dolor", + iconClass : "fa fa-shield", + href: "#/dolor", + badges: [ + { + count: 1283, + tooltip: "Total number of items" + } + ] + }, + { + title: "Ipsum", + iconClass: "fa fa-space-shuttle", + children: [ + { + title: "Intellegam", + children: [ + { + title: "Recteque", + href: "#/ipsum/intellegam/recteque", + badges: [ + { + count: 6, + tooltip: "Total number of error items", + badgeClass: 'example-error-background' + } + ] + }, + { + title: "Suavitate", + href: "#/ipsum/intellegam/suavitate", + badges: [ + { + count: 2, + tooltip: "Total number of items" + } + ] + }, + { + title: "Vituperatoribus", + href: "#/ipsum/intellegam/vituperatoribus", + badges: [ + { + count: 18, + tooltip: "Total number of warning items", + badgeClass: 'example-warning-background' + } + ] + } + ] + }, + { + title: "Copiosae", + children: [ + { + title: "Exerci", + href: "#/ipsum/copiosae/exerci", + badges: [ + { + count: 2, + tooltip: "Total number of error items", + iconClass: 'pficon pficon-error-circle-o' + }, + { + count: 6, + tooltip: "Total number warning error items", + iconClass: 'pficon pficon-warning-triangle-o' + } + ] + }, + { + title: "Quaeque", + href: "#/ipsum/copiosae/quaeque", + badges: [ + { + count: 0, + tooltip: "Total number of error items", + iconClass: 'pficon pficon-error-circle-o' + }, + { + count: 4, + tooltip: "Total number warning error items", + iconClass: 'pficon pficon-warning-triangle-o' + } + ] + }, + { + title: "Utroque", + href: "#/ipsum/copiosae/utroque", + badges: [ + { + count: 1, + tooltip: "Total number of error items", + iconClass: 'pficon pficon-error-circle-o' + }, + { + count: 2, + tooltip: "Total number warning error items", + iconClass: 'pficon pficon-warning-triangle-o' + } + ] + } + ] + }, + { + title: "Patrioque", + children: [ + { + title: "Novum", + href: "#/ipsum/patrioque/novum" + }, + { + title: "Pericula", + href: "#/ipsum/patrioque/pericula" + }, + { + title: "Gubergren", + href: "#/ipsum/patrioque/gubergren" + } + ] + }, + { + title: "Accumsan", + href: "#/ipsum/Accumsan", + badges: [ + { + count: 2, + tooltip: "Total number of error items", + iconClass: 'pficon pficon-error-circle-o' + }, + { + count: 6, + tooltip: "Total number warning error items", + iconClass: 'pficon pficon-warning-triangle-o' + } + ] + } + ] + }, + { + title: "Amet", + iconClass: "fa fa-paper-plane", + children: [ + { + title: "Detracto", + children: [ + { + title: "Delicatissimi", + href: "#/amet/detracto/delicatissimi" + }, + { + title: "Aliquam", + href: "#/amet/detracto/aliquam" + }, + { + title: "Principes", + href: "#/amet/detracto/principes" + } + ] + }, + { + title: "Mediocrem", + children: [ + { + title: "Convenire", + href: "#/amet/mediocrem/convenire" + }, + { + title: "Nonumy", + href: "#/amet/mediocrem/nonumy" + }, + { + title: "Deserunt", + href: "#/amet/mediocrem/deserunt" + } + ] + }, + { + title: "Corrumpit", + children: [ + { + title: "Aeque", + href: "#/amet/corrumpit/aeque" + }, + { + title: "Delenit", + href: "#/amet/corrumpit/delenit" + }, + { + title: "Qualisque", + href: "#/amet/corrumpit/qualisque" + } + ] + }, + { + title: "urbanitas", + href: "#/amet/urbanitas" + } + ] + }, + { + title: "Adipscing", + iconClass: "fa fa-graduation-cap", + href: "#/adipscing" + }, + { + title: "Lorem", + iconClass: "fa fa-gamepad", + href: "#/lorem" + }, + { + title: "Exit Demo" + } + ]; + $scope.handleNavigateClick = function (item) { + if (item.title === "Exit Demo") { + angular.element(document.querySelector("#verticalNavLayout")).addClass("hidden"); + } + }; + } + ]); + + + $(document).ready(function() { + $("#includedContent")[0].innerHTML = '\ +
\ +
\ +
\ +

\ + 0 Ipsum\ +

\ +
\ +

\ + \ +

\ +
\ +
\ +
\ +
\ +
\ +

\ + 20 Amet\ +

\ +
\ +

\ + 4\ + 1\ +

\ +
\ +
\ +
\ +
\ +
\ +

\ + 9 Adipiscing\ +

\ +
\ +

\ + \ +

\ +
\ +
\ +
\ +
\ +
\ +

\ + 12 Lorem\ +

\ +
\ +

\ + 1\ +

\ +
\ +
\ +
\ +
\ +
\ +
\ +
\ +

\ + \ + 0 Ipsum\ +

\ +
\ +

\ + \ +

\ +
\ +
\ +
\ +
\ +
\ +

\ + \ + \ + 20 Amet\ + \ +

\ +
\ +

\ + 4\ +

\ +
\ +
\ +
\ +
\ +
\ +

\ + \ + \ + 9 Adipiscing\ + \ +

\ +
\ +

\ + \ +

\ +
\ +
\ +
\ +
\ +
\ +

\ + \ + \ + 12 Lorem\ + \ +

\ +
\ +

\ + 1\ +

\ +
\ +
\ +
\ +
\ +
\ +
\ +
\ +
\ +

\ + Top Utilized\ +

\ +
\ +
\ +
\ + Ipsum\ +
\ +
\ +
\ + 190.0 of 200.0 GB Used\ +
\ +
\ + 5% Available\ +
\ +
\ +
\ + Amet\ +
\ +
\ +
\ + 100.0 of 200.0 GB Used\ +
\ +
\ + 50% Available\ +
\ +
\ +
\ + Adipiscing\ +
\ +
\ +
\ + 140.0 of 200.0 GB Used\ +
\ +
\ + 30% Available\ +
\ +
\ +
\ + Lorem\ +
\ +
\ +
\ + 153.0 of 200.0 GB Used\ +
\ +
\ + 23.5% Available\ +
\ +
\ +
\ +
\ +
\ +
\ +
\ +
\ +

\ + Quotas\ +

\ +
\ +
\ +
\ +
\ + Ipsum\ +
\ +
\ +
\ + 115 of 460 MHz\ +
\ +
\ + 75% Available\ +
\ +
\ +
\ +
\ +
\ + Amet\ +
\ +
\ +
\ + 8 of 16 GB\ +
\ +
\ + 50% Available\ +
\ +
\ +
\ +
\ +
\ + Adipiscing\ +
\ +
\ +
\ + 5 of 8 Total\ +
\ +
\ + 37.5% Available\ +
\ +
\ +
\ +
\ +
\ + Lorem\ +
\ +
\ +
\ + 2 of 2 Total\ +
\ +
\ +
\ +
\ +
\ +
\ +
\ + '; + }); +
+ + $(document).ready(function() { + $(document).on('click', '#showVerticalNav', function() { + $(document.getElementById("verticalNavLayout")).removeClass("hidden"); + }); + $(document).on('click', '#hideVerticalNav', function() { + $(document.getElementById("verticalNavLayout")).addClass("hidden"); + }); + }); + +
+*/ \ No newline at end of file diff --git a/src/navigation/examples/vertical-navigation-router.js b/src/navigation/examples/vertical-navigation-router.js new file mode 100644 index 000000000..4366ee376 --- /dev/null +++ b/src/navigation/examples/vertical-navigation-router.js @@ -0,0 +1,159 @@ +/** + * @ngdoc directive + * @name patternfly.navigation.directive:pfVerticalNavigation - Router + * + * @description + * This example shows how to use pfVerticalNavigation with angular-ui-router's $states and uiSrefs. + * + * @param {string} brandSrc src for brand image + * @param {string} brandAlt Text for product name when brand image is not available + * @param {boolean} showBadges Flag if badges are used on navigation items, default: false + * @param {boolean} persistentSecondary Flag to use persistent secondary menus, default: false + * @param {boolean} hiddenIcons Flag to not show icons on the primary menu, default: false + * @param {array} items List of navigation items + * + * @param {function} navigateCallback function(item) Callback method invoked on a navigation item click (one with no submenus) + * @param {function} itemClickCallback function(item) Callback method invoked on an item click + * @param {boolean} updateActiveItemsOnClick Flag if active items should be marked on click rather than on navigation change, default: false + * @param {boolean} ignoreMobile Flag if mobile state should be ignored (use only if absolutely necessary) default: false + * + * @example + + +
+ + + +
+ +
+ + angular.module('myApp',['patternfly.navigation', 'ui.router']) + .config(function($stateProvider, $urlRouterProvider) { + $urlRouterProvider.otherwise('dashboard'); + + $stateProvider + .state('dashboard', { + url: '/dashboard', + template: '
\ +
\ +

\ + State: Dashboard\ +

\ +
\ +
' + }) + .state('dolor', { + url: '/dolor', + template: '
\ +
\ +

\ + State: Dolor\ +

\ +
\ +
' + }) + .state('ipsum', { + url: '/ipsum', + template: '
\ +
\ +

\ + State: Ipsum\ +

\ +
\ +
' + }); + }) + .controller('vertNavWithRouterController', ['$scope', + function ($scope) { + $scope.navigationItems = [ + { + title: "Dashboard", + iconClass: "fa fa-dashboard", + uiSref: "dashboard" + }, + { + title: "Dolor", + iconClass : "fa fa-shield", + uiSref: "dolor" + }, + { + title: "Ipsum", + iconClass : "fa fa-space-shuttle", + uiSref: "ipsum" + }, + { + title: "Exit Demo" + } + ]; + $scope.handleNavigateClickRouter = function (item) { + if (item.title === "Exit Demo") { + angular.element(document.querySelector("#verticalNavWithRouterLayout")).addClass("hidden"); + } + }; + } + ]); +
+ + $(document).ready(function() { + $(document).on('click', '#showVerticalNavWithRouter', function() { + $(document.getElementById("verticalNavWithRouterLayout")).removeClass("hidden"); + }); + $(document).on('click', '#hideVerticalNavWithRouter', function() { + $(document.getElementById("verticalNavWithRouterLayout")).addClass("hidden"); + }); + }); + +
+*/ \ No newline at end of file diff --git a/src/navigation/vertical-navigation-directive.js b/src/navigation/vertical-navigation-directive.js index fc2992b2d..eef1520ca 100755 --- a/src/navigation/vertical-navigation-directive.js +++ b/src/navigation/vertical-navigation-directive.js @@ -1,573 +1,13 @@ -/** - * @ngdoc directive - * @name patternfly.navigation.directive:pfVerticalNavigation - * - * @description - * Directive for vertical navigation. This sets up the nav bar header with the collapse button (hamburger) and the - * application brand image (or text) as well as the vertical navigation bar containing the navigation items. This - * directive supports primary, secondary, and tertiary navigation with options to allow pinning of the secondary and - * tertiary navigation menus as well as the option for persistent secondary menus. - *

- * The remaining parts of the navbar header can be transcluded. - *

- * Tha navigation items are marked active based on the current location and the href value for the item. If not using - * href's on the items to navigate, set update-active-items-on-click to "true". - *

- * This directive works in conjunction with the main content container if the 'container-pf-nav-pf-vertical' class - * selector is added to the main content container. - * - * @param {string} brandSrc src for brand image - * @param {string} brandAlt Text for product name when brand image is not available - * @param {boolean} showBadges Flag if badges are used on navigation items, default: false - * @param {boolean} persistentSecondary Flag to use persistent secondary menus, default: false - * @param {boolean} hiddenIcons Flag to not show icons on the primary menu, default: false - * @param {array} items List of navigation items - * - * @param {function} navigateCallback function(item) Callback method invoked on a navigation item click (one with no submenus) - * @param {function} itemClickCallback function(item) Callback method invoked on an item click - * @param {boolean} updateActiveItemsOnClick Flag if active items should be marked on click rather than on navigation change, default: false - * @param {boolean} ignoreMobile Flag if mobile state should be ignored (use only if absolutely necessary) default: false - * - * @example - - -
- - - -
- -
- - angular.module('patternfly.navigation').controller('vertNavController', ['$scope', - function ($scope) { - $scope.navigationItems = [ - { - title: "Dashboard", - iconClass: "fa fa-dashboard", - href: "#/dashboard" - }, - { - title: "Dolor", - iconClass : "fa fa-shield", - href: "#/dolor", - badges: [ - { - count: 1283, - tooltip: "Total number of items" - } - ] - }, - { - title: "Ipsum", - iconClass: "fa fa-space-shuttle", - children: [ - { - title: "Intellegam", - children: [ - { - title: "Recteque", - href: "#/ipsum/intellegam/recteque", - badges: [ - { - count: 6, - tooltip: "Total number of error items", - badgeClass: 'example-error-background' - } - ] - }, - { - title: "Suavitate", - href: "#/ipsum/intellegam/suavitate", - badges: [ - { - count: 2, - tooltip: "Total number of items" - } - ] - }, - { - title: "Vituperatoribus", - href: "#/ipsum/intellegam/vituperatoribus", - badges: [ - { - count: 18, - tooltip: "Total number of warning items", - badgeClass: 'example-warning-background' - } - ] - } - ] - }, - { - title: "Copiosae", - children: [ - { - title: "Exerci", - href: "#/ipsum/copiosae/exerci", - badges: [ - { - count: 2, - tooltip: "Total number of error items", - iconClass: 'pficon pficon-error-circle-o' - }, - { - count: 6, - tooltip: "Total number warning error items", - iconClass: 'pficon pficon-warning-triangle-o' - } - ] - }, - { - title: "Quaeque", - href: "#/ipsum/copiosae/quaeque", - badges: [ - { - count: 0, - tooltip: "Total number of error items", - iconClass: 'pficon pficon-error-circle-o' - }, - { - count: 4, - tooltip: "Total number warning error items", - iconClass: 'pficon pficon-warning-triangle-o' - } - ] - }, - { - title: "Utroque", - href: "#/ipsum/copiosae/utroque", - badges: [ - { - count: 1, - tooltip: "Total number of error items", - iconClass: 'pficon pficon-error-circle-o' - }, - { - count: 2, - tooltip: "Total number warning error items", - iconClass: 'pficon pficon-warning-triangle-o' - } - ] - } - ] - }, - { - title: "Patrioque", - children: [ - { - title: "Novum", - href: "#/ipsum/patrioque/novum" - }, - { - title: "Pericula", - href: "#/ipsum/patrioque/pericula" - }, - { - title: "Gubergren", - href: "#/ipsum/patrioque/gubergren" - } - ] - }, - { - title: "Accumsan", - href: "#/ipsum/Accumsan", - badges: [ - { - count: 2, - tooltip: "Total number of error items", - iconClass: 'pficon pficon-error-circle-o' - }, - { - count: 6, - tooltip: "Total number warning error items", - iconClass: 'pficon pficon-warning-triangle-o' - } - ] - } - ] - }, - { - title: "Amet", - iconClass: "fa fa-paper-plane", - children: [ - { - title: "Detracto", - children: [ - { - title: "Delicatissimi", - href: "#/amet/detracto/delicatissimi" - }, - { - title: "Aliquam", - href: "#/amet/detracto/aliquam" - }, - { - title: "Principes", - href: "#/amet/detracto/principes" - } - ] - }, - { - title: "Mediocrem", - children: [ - { - title: "Convenire", - href: "#/amet/mediocrem/convenire" - }, - { - title: "Nonumy", - href: "#/amet/mediocrem/nonumy" - }, - { - title: "Deserunt", - href: "#/amet/mediocrem/deserunt" - } - ] - }, - { - title: "Corrumpit", - children: [ - { - title: "Aeque", - href: "#/amet/corrumpit/aeque" - }, - { - title: "Delenit", - href: "#/amet/corrumpit/delenit" - }, - { - title: "Qualisque", - href: "#/amet/corrumpit/qualisque" - } - ] - }, - { - title: "urbanitas", - href: "#/amet/urbanitas" - } - ] - }, - { - title: "Adipscing", - iconClass: "fa fa-graduation-cap", - href: "#/adipscing" - }, - { - title: "Lorem", - iconClass: "fa fa-gamepad", - href: "#/lorem" - }, - { - title: "Exit Demo" - } - ]; - $scope.handleNavigateClick = function (item) { - if (item.title === "Exit Demo") { - angular.element(document.querySelector("#verticalNavLayout")).addClass("hidden"); - } - }; - } - ]); - - - $(document).ready(function() { - $("#includedContent")[0].innerHTML = '\ -
\ -
\ -
\ -

\ - 0 Ipsum\ -

\ -
\ -

\ - \ -

\ -
\ -
\ -
\ -
\ -
\ -

\ - 20 Amet\ -

\ -
\ -

\ - 4\ - 1\ -

\ -
\ -
\ -
\ -
\ -
\ -

\ - 9 Adipiscing\ -

\ -
\ -

\ - \ -

\ -
\ -
\ -
\ -
\ -
\ -

\ - 12 Lorem\ -

\ -
\ -

\ - 1\ -

\ -
\ -
\ -
\ -
\ -
\ -
\ -
\ -

\ - \ - 0 Ipsum\ -

\ -
\ -

\ - \ -

\ -
\ -
\ -
\ -
\ -
\ -

\ - \ - \ - 20 Amet\ - \ -

\ -
\ -

\ - 4\ -

\ -
\ -
\ -
\ -
\ -
\ -

\ - \ - \ - 9 Adipiscing\ - \ -

\ -
\ -

\ - \ -

\ -
\ -
\ -
\ -
\ -
\ -

\ - \ - \ - 12 Lorem\ - \ -

\ -
\ -

\ - 1\ -

\ -
\ -
\ -
\ -
\ -
\ -
\ -
\ -
\ -

\ - Top Utilized\ -

\ -
\ -
\ -
\ - Ipsum\ -
\ -
\ -
\ - 190.0 of 200.0 GB Used\ -
\ -
\ - 5% Available\ -
\ -
\ -
\ - Amet\ -
\ -
\ -
\ - 100.0 of 200.0 GB Used\ -
\ -
\ - 50% Available\ -
\ -
\ -
\ - Adipiscing\ -
\ -
\ -
\ - 140.0 of 200.0 GB Used\ -
\ -
\ - 30% Available\ -
\ -
\ -
\ - Lorem\ -
\ -
\ -
\ - 153.0 of 200.0 GB Used\ -
\ -
\ - 23.5% Available\ -
\ -
\ -
\ -
\ -
\ -
\ -
\ -
\ -

\ - Quotas\ -

\ -
\ -
\ -
\ -
\ - Ipsum\ -
\ -
\ -
\ - 115 of 460 MHz\ -
\ -
\ - 75% Available\ -
\ -
\ -
\ -
\ -
\ - Amet\ -
\ -
\ -
\ - 8 of 16 GB\ -
\ -
\ - 50% Available\ -
\ -
\ -
\ -
\ -
\ - Adipiscing\ -
\ -
\ -
\ - 5 of 8 Total\ -
\ -
\ - 37.5% Available\ -
\ -
\ -
\ -
\ -
\ - Lorem\ -
\ -
\ -
\ - 2 of 2 Total\ -
\ -
\ -
\ -
\ -
\ -
\ -
\ - '; - }); -
- - $(document).ready(function() { - $(document).on('click', '#showVerticalNav', function() { - $(document.getElementById("verticalNavLayout")).removeClass("hidden"); - }); - $(document).on('click', '#hideVerticalNav', function() { - $(document.getElementById("verticalNavLayout")).addClass("hidden"); - }); - }); - -
-*/ - angular.module('patternfly.navigation').directive('pfVerticalNavigation', ['$location', '$rootScope', '$window', '$document', '$timeout', - function (location, rootScope, $window, $document, $timeout) { +angular.module('patternfly.navigation').directive('pfVerticalNavigation', ['$location', '$rootScope', '$window', '$document', '$timeout', '$injector', + function (location, rootScope, $window, $document, $timeout, $injector) { 'use strict'; + var $state; + + // Optional dependency on $state + if ($injector.has("$state")) { + $state = $injector.get("$state"); + } + return { restrict: 'A', scope: { @@ -826,12 +266,23 @@ var navTo; if (navItem) { $scope.showMobileNav = false; - navTo = navItem.href; - if (navTo) { - if (navTo.startsWith('#/')) { - navTo = navTo.substring(2); + if (navItem.uiSref && navItem.href) { + throw new Error('Using both uiSref and href on an item is not supported.'); + } + if (navItem.uiSref) { + if ($state === undefined) { + throw new Error('uiSref is defined on item, but no $state has been injected. ' + + 'Did you declare a dependency on "ui.router" module in your app?'); + } + $state.go(navItem.uiSref, navItem.uiSrefOptions); + } else { + navTo = navItem.href; + if (navTo) { + if (navTo.startsWith('#/')) { + navTo = navTo.substring(2); + } + location.path(navTo); } - location.path(navTo); } if ($scope.navigateCallback) { $scope.navigateCallback(navItem); diff --git a/test/karma.conf.js b/test/karma.conf.js index 6b8602239..34b8a6692 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -28,7 +28,8 @@ module.exports = function(config) { 'test/utils/*.js', 'test/wizard/script.js', 'test/**/*.spec.js', - 'test/**/*.html' + 'test/**/*.html', + 'lib/angular-ui-router/release/angular-ui-router.min.js' ], // list of files to exclude diff --git a/test/navigation/vertical-navigation.spec.js b/test/navigation/vertical-navigation.spec.js index f646f8fc2..1ec19783d 100644 --- a/test/navigation/vertical-navigation.spec.js +++ b/test/navigation/vertical-navigation.spec.js @@ -32,7 +32,7 @@ describe('Directive: pfVerticalNavigation', function () { { title: "Dolor", iconClass : "fa fa-shield", - href: "#/dolor", + uiSref: "dolor", badges: [ { count: 1283, @@ -691,4 +691,134 @@ describe('Directive: pfVerticalNavigation', function () { expect(badgesShown.length).toBe(0); }); + it('should throw and error if uiSref is used when $state is undefined', function () { + var wellDefinedItem = element.find('.nav-pf-vertical > .list-group > .list-group-item:nth-child(2) > a'); + expect(function() { + wellDefinedItem.click(); + }).toThrow(new Error("uiSref is defined on item, but no $state has been injected. Did you declare a dependency on \"ui.router\" module in your app?")); + }); }); + + +describe('Directive: pfVerticalNavigation with ui.router', function () { + // Setting up some dummy controllers and some dummy states + angular.module('mockApp', ['ui.router']) + .controller('Controller0', function() { + this.message = 'Page 0'; + }).controller('Controller1', function() { + this.message = 'Page 1'; + }).config(function($stateProvider, $urlRouterProvider) { + $urlRouterProvider.otherwise("/state0"); + + $stateProvider.state('state0', { + url: "/state0", + controller: 'Controller0', + controllerAs: 'vm' + }).state('state1', { + url: "/state1", + controller: 'Controller1', + controllerAs: 'vm' + }); + }); + + var $state; + var $scope; + var $compile; + var element; + var isolateScope; + + // load the controller's module + beforeEach(function () { + module('patternfly.navigation', 'patternfly.utils', 'navigation/vertical-navigation.html'); + }); + + beforeEach(module('mockApp')); + + beforeEach(inject(function (_$compile_, _$rootScope_, _$state_) { + $compile = _$compile_; + $scope = _$rootScope_; + $state = _$state_; + + spyOn($state, 'go').and.callThrough(); + })); + + var compileHTML = function (markup, scope) { + element = angular.element(markup); + $compile(element)(scope); + + scope.$digest(); + isolateScope = element.isolateScope(); + }; + + beforeEach(function () { + $scope.navigationItems = [ + { + title: "Dashboard", + iconClass: "fa fa-dashboard", + uiSref: 'state1', + uiSrefOptions: 'testing' + }, + { + title: "Dolor", + iconClass : "fa fa-shield", + href: "#/state2", + uiSref: 'state2', + badges: [ + { + count: 1283, + tooltip: "Total number of items" + } + ] + } + ]; + + $scope.handleNavigateClick = function (item) { + $scope.navigateItem = item.title; + }; + + $scope.handleItemClick = function (item) { + $scope.clickItem = item.title; + }; + + var htmlTmp = '' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + ' ' + + ''; + + compileHTML(htmlTmp, $scope); + }); + + it('should trigger the $state.go() function when an item with ui-sref defined is clicked', function () { + var wellDefinedItem = element.find('.nav-pf-vertical > .list-group > .list-group-item:nth-child(1) > a'); + + expect($state.current.name).toBe("state0"); + + // Click dashboard item + wellDefinedItem.click(); + + expect($state.go).toHaveBeenCalledWith('state1','testing'); + + // Checking successful state transition + expect($state.current.name).toBe("state1"); + expect($state.current.controller).toBe("Controller1"); + }); + + it('should throw and error if both uiSref and href are used on an item', function () { + var badDefinedItem = element.find('.nav-pf-vertical > .list-group > .list-group-item:nth-child(2) > a'); + + expect( function() { + badDefinedItem.click(); + }).toThrow(new Error('Using both uiSref and href on an item is not supported.')); + }); +}); +