How to keep the menu header in service portal visible all the time?

YenGar
Mega Sage

Hi community, 

Is there a way to keep the header menus (My requests, my approvals', etc) in the header menu of the service portal always visible even if the user doesn't have anything there?

Currently, the menus only show when the user has at least one item in those menus but we need it to show all the time. 

I have modified the menuTemplate to see if it would keep it visible but it didn't do anything. I also cloned the header menu widget and it didn't show anything at all in the header... Please see below. 

Updated menuTemplate

<a ng-if="item.items.length == 0 && !item.scriptedItems" ng-href="{{item.href}}">{{ item.label }}</a>
<a ng-if="item.items.length > 0" href="javascript:void(0)" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{ item.label }} <span class="caret"></span></a>
<ul ng-if="item.items.length > 0" class="dropdown-menu" role="menu">
    <li ng-repeat="item in item.items" ng-include="'menuTemplate'" />
</ul>
<a   ng-if="item.scriptedItems.count" href="javascript:void(0)" data-toggle="dropdown" title="{{item.hint}}">
   <span ng-bind-html="item.label"></span>
       <span ng-if="!item.scriptedItems.omitBadge" class="label label-as-badge label-primary sp-navbar-badge-count">{{item.scriptedItems.count}}</span>
</a>

<sp-dropdown-tree ng-if="item.scriptedItems.count" items="item.scriptedItems.items" />

Updated Menu Header Widget - client script (line 47)

function ($scope, spUtil, $rootScope, $timeout, spAriaUtil) {
	$scope.loadingIndicator = $rootScope.loadingIndicator;
	$scope.cartItemCount = 0;
	$scope.wishlistItemCount = 0;
	$scope.itemAddedTooltipOpen = false;

	$scope.accessibilityEnabled = spAriaUtil.g_accessibility === "true";

	$scope.$on("$sp.service_catalog.cart.count", function($evt, count) {
		$scope.cartItemCount = count;
	});

	$scope.$on("$sp.service_catalog.wishlist.count", function($evt, count) {
		$scope.wishlistItemCount = count;
	});

	var cancelTooltipPromise;
	$scope.$on("$sp.service_catalog.cart.add_item", function() {
		$timeout.cancel(cancelTooltipPromise);

		$scope.itemAddedTooltipOpen = true;
		cancelTooltipPromise = $timeout(function() {
			$scope.itemAddedTooltipOpen = false;
		}, 3000);
	});

	$scope.$on('sp_loading_indicator', function(e, value) {
		$scope.loadingIndicator = value;
	});

	$scope.toggleCart = function() {
		$timeout.cancel(cancelTooltipPromise);
		$scope.itemAddedTooltipOpen = false;
		$timeout(function() {
			$("#cart-dropdown").dropdown("toggle");
		});
	};

	// PRB1108244: visibleItems array is used to improve keyboard nav 
	// in menu, refresh it as needed
	$scope.$watch('data.menu.items', function() {
		$scope.visibleItems = [];
		if ($scope.data.menu.items) {
			for (var i in $scope.data.menu.items) {
				var item = $scope.data.menu.items[i];
				if (item.items || (item.scriptedItems && item.scriptedItems.count >= 0))
					$scope.visibleItems.push(item);
			}
		}
	}, true);

	// Get list of record watchers
	var record_watchers = [];
	if ($scope.data.menu.items) {
		for(var i in $scope.data.menu.items) {
			var item = $scope.data.menu.items[i];
			if (item.type == 'scripted') {
				if (item.scriptedItems.record_watchers)
					record_watchers = record_watchers.concat(item.scriptedItems.record_watchers);
			}
			if (item.type == 'filtered') {
				record_watchers.push({'table':item.table,'filter':item.filter});
			}
		}
	}

	// Init record watchers
	for (var y in record_watchers){
		var watcher = record_watchers[y];
		spUtil.recordWatch($scope, watcher.table, watcher.filter);
	}
}

 

Can anyone tell me what I am doing wrong? How can I get the header menus show up all the time?

 

Any help is appreciated!

 

Thank you, 

Yeny

 

1 ACCEPTED SOLUTION

Allen Andreas
Administrator
Administrator

I'm on Kingston and this works for me...

menuTemplate:

<a ng-if="item.items.length == 0 && !item.scriptedItems" ng-href="{{::item.href}}" target="{{::item.url_target}}" title="{{::item.hint}}">
  <fa ng-if="::item.glyph" name="{{::item.glyph}}"></fa>
  <span ng-bind-html="::item.label"></span>
</a>
<a role="button" ng-if="item.items.length > 0" href class="dropdown-toggle sp-menu-has-items" data-toggle="dropdown" aria-controls="menu-apply" aria-haspopup="true" title="{{::item.hint}}">
  <fa ng-if="::item.glyph" name="{{::item.glyph}}"></fa>
  <span ng-bind-html="::item.label"></span> <span class="caret"></span>
</a>
<ul ng-if="item.items.length > 0" class="dropdown-menu" role="group" id="menu-apply">
  <li ng-repeat="item in item.items" ng-include="'menuTemplate'" />
</ul>
<a role="button" ng-if="item.scriptedItems.count >= 0" href data-toggle="dropdown" title="{{::item.hint}}">
  <fa ng-if="::item.glyph" name="{{::item.glyph}}"></fa>
  <span ng-bind-html="::item.label"></span>
  <span ng-if="::!item.scriptedItems.omitBadge" class="label label-as-badge label-primary sp-navbar-badge-count">{{item.scriptedItems.count}}</span>
</a>
<sp-dropdown-tree role="menu" aria-label="{{::item.label}}" ng-if="item.scriptedItems.count >= 0" items="item.scriptedItems.items" />

 

Client Controller:

function ($scope, spUtil, $rootScope, $timeout, spAriaUtil) {
	$scope.loadingIndicator = $rootScope.loadingIndicator;
	$scope.cartItemCount = 0;
	$scope.wishlistItemCount = 0;
	$scope.itemAddedTooltipOpen = false;

	$scope.accessibilityEnabled = spAriaUtil.g_accessibility === "true";

	$scope.$on("$sp.service_catalog.cart.count", function($evt, count) {
		$scope.cartItemCount = count;
	});

	$scope.$on("$sp.service_catalog.wishlist.count", function($evt, count) {
		$scope.wishlistItemCount = count;
	});

	var cancelTooltipPromise;
	$scope.$on("$sp.service_catalog.cart.add_item", function() {
		$timeout.cancel(cancelTooltipPromise);

		$scope.itemAddedTooltipOpen = true;
		cancelTooltipPromise = $timeout(function() {
			$scope.itemAddedTooltipOpen = false;
		}, 3000);
	});

	$scope.$on('sp_loading_indicator', function(e, value) {
		$scope.loadingIndicator = value;
	});

	$scope.toggleCart = function() {
		$timeout.cancel(cancelTooltipPromise);
		$scope.itemAddedTooltipOpen = false;
		$timeout(function() {
			$("#cart-dropdown").dropdown("toggle");
		});
	};

	// PRB1108244: visibleItems array is used to improve keyboard nav 
	// in menu, refresh it as needed
	$scope.$watch('data.menu.items', function() {
		$scope.visibleItems = [];
		if ($scope.data.menu.items) {
			for (var i in $scope.data.menu.items) {
				var item = $scope.data.menu.items[i];
				if (item.items || (item.scriptedItems && item.scriptedItems.count >= 0))
					$scope.visibleItems.push(item);
			}
		}
	}, true);

	// Get list of record watchers
	var record_watchers = [];
	if ($scope.data.menu.items) {
		for(var i in $scope.data.menu.items) {
			var item = $scope.data.menu.items[i];
			if (item.type == 'scripted') {
				if (item.scriptedItems.record_watchers)
					record_watchers = record_watchers.concat(item.scriptedItems.record_watchers);
			}
			if (item.type == 'filtered') {
				record_watchers.push({'table':item.table,'filter':item.filter});
			}
		}
	}

	// Init record watchers
	for (var y in record_watchers){
		var watcher = record_watchers[y];
		spUtil.recordWatch($scope, watcher.table, watcher.filter);
	}
}

 

Then just make sure you associate this correctly to your menutemplate and other angular ng-templates (should be at least 3)


Please consider marking my reply as Helpful and/or Accept Solution, if applicable. Thanks!

View solution in original post

22 REPLIES 22

ryanlitwiller
Giga Guru

Try removing .count in your template:

find_real_file.png

Like below:

<a ng-if="item.items.length == 0 && !item.scriptedItems" ng-href="{{item.href}}">{{ item.label }}</a>
<a ng-if="item.items.length > 0" href="javascript:void(0)" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{ item.label }} <span class="caret"></span></a>
<ul ng-if="item.items.length > 0" class="dropdown-menu" role="menu">
    <li ng-repeat="item in item.items" ng-include="'menuTemplate'" />
</ul>
<a   ng-if="item.scriptedItems" href="javascript:void(0)" data-toggle="dropdown" title="{{item.hint}}">
   <span ng-bind-html="item.label"></span>
       <span ng-if="!item.scriptedItems.omitBadge" class="label label-as-badge label-primary sp-navbar-badge-count">{{item.scriptedItems.count}}</span>
</a>

<sp-dropdown-tree ng-if="item.scriptedItems" items="item.scriptedItems.items" />

Ian Mildon
Tera Guru

Most of the previous methods of doing this no longer work on Kingston. Your only real options now are to clone the widget so you can edit the scripting (several posts on here with links to how to do this) or you can replace the scripted lists for page links (will require creating the pages that mimic the scripted lists).

Yea, thanks. You reply to all of these saying this, lol. Obviously they've already cloned it, now they're just checking their script.


Please consider marking my reply as Helpful and/or Accept Solution, if applicable. Thanks!

With the number of people wanting to do this, I think ServiceNow should make this an easier fix, rather than having to resort to cloning a widget and then editing the scripts.