Header menu on new Service portal
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
05-15-2017 11:09 AM
Ok I have seen many post on the header menu being cloned and followed the directions in threads such as Service Portal Header Menu Issue
Note: I am not used to working with angular and am strictly going off articles read. I may be missing something small.
What I am trying to accomplish:
- Change the cart button to redirect to a custom widget for the cart.
What I have done.
- Created new cart widget named ssp_shopping_cart by cloning current cart widget, copied and renamed Angular ng-template scripts from original widget to ssp_large_shopping_cart.html and ssp_small_shopping_cart.html
- Cloned header menu, Copied and renamed angular ng-templates to sspDropdownTreeTemplate and sspMenuTemplate
- Created angular provider directive named sspDropdownTree with the following code and then went into the angular templates and edited the bottom line at each to match the directive as suggested in the article linked above.
</a>
<ssp-dropdown-tree ng-if="mi.type == 'menu' && mi.items.length" items="mi.items" />
/*! RESOURCE: /scripts/app.$sp/directive.spDropdownTree.js */
/* angular.module('sn.$sp').directive('spDropdownCustom', */
function () {
return {
restrict: 'E',
scope: {items: '='},
replace: true,
template: '<ul class="dropdown-menu">' +
'<li ng-repeat="mi in items" style="min-width: 20em;" ng-class="{\'dropdown-submenu\': mi.type == \'menu\', \'dropdown-menu-line\':$index < items.length - 1}" ng-include="getURL()">' +
'</ul>',
link : function(scope, element, attrs, controller) {
scope.getURL = function() {
return 'sspDropdownTreeTemplate';
}
}
}
};
(function($) {
$("body").on( "click", "a.menu_trigger", function(e) {
var current = $(this).next();
var grandparent = $(this).parent().parent();
if ($(this).hasClass('left-caret') || $(this).hasClass('right-caret'))
$(this).toggleClass('right-caret left-caret');
grandparent.find('.left-caret').not(this).toggleClass('right-caret left-caret');
current.toggle();
$(".dropdown-menu").each(function(i, elem) {
var elemClosest = $(elem).closest('.dropdown');
var currentClosest = current.closest('.dropdown');
if (!elem.contains(current[0]) && elem != current[0] && (!currentClosest.length || !elemClosest.length || elemClosest[0] == currentClosest[0]))
$(elem).hide();
})
e.stopPropagation();
});
$("body").on( "click", "a:not(.menu_trigger)", function() {
var root=$(this).closest('.dropdown');
root.find('.left-caret').toggleClass('right-caret left-caret');
});
})(jQuery);
;
Problem:
- First problem I have had is the links we have for 'Service Catalog' 'Request' and 'Switch to Legacy' start to load but time out and I am unable to click on anything that point. the cart and my user name do show up.... but there is no functionality to them.
It's worth noting that if I just take the OOTB header menu, clone it and add the angular ng-templates to it without any further edits the same behavior is observed. At that point if I had the angular provider directive, the same thing occurs.
Any help is appreciated. I like the new Service Portal, this part is just throwing me for a loop.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-22-2017 07:12 AM
have you tried this ? https://github.com/service-portal/documentation/issues/50

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-10-2017 05:42 AM
Were you able to ever get this to work? I have followed the thread in the github and made my own directive, pointed the ng-templates to it, but my menu won't load. It looks like it's thinking for a while and then changes the menu black with the only option being the cart (which won't allow me to click on it - or on any of the links on the rest of the page either).
Sorry, I really don't understand angular. I highlighted the parts that I changed to point to the custom angular. This is the code from the various parts of this attempted change.
ITSC Header Menu (HMTL)
<ul class="nav navbar-nav">
<div class="header-loader" ng-show="loadingIndicator">
<div class="hidden-xs sp-loading-indicator la-sm">
<div></div>
<div></div>
<div></div>
</div>
</div>
<li ng-repeat="item in data.menu.items" ng-class="{dropdown: item.items.length > 0}" ng-include="'ITSCmenuTemplate'"></li>
<!-- Shopping cart stuff -->
<li ng-if="options.enable_cart && data.isLoggedIn" class="dropdown hidden-xs">
<a href="javascript:void(0)"
data-toggle="dropdown"
id="cart-dropdown"
uib-tooltip-template="'item-added-tooltip.html'"
tooltip-placement="bottom"
tooltip-trigger="'none'"
tooltip-is-open="$parent.itemAddedTooltipOpen"
title="${Cart}">
<i class="fa fa-shopping-cart" aria-hidden="true"></i>
<span ng-bind-html="'${Cart}'"></span>
<span ng-if="cartItemCount > 0" class="label label-as-badge label-primary sp-navbar-badge-count">{{cartItemCount}}</span>
</a>
<div class="dropdown-menu cart-dropdown">
<sp-widget widget="data.cartWidget"></sp-widget>
</div>
</li>
<li ng-if="options.enable_cart && data.isLoggedIn" class="dropdown visible-xs">
<a href="?id=sc_cart"
title="${Cart}">
<i class="fa fa-shopping-cart" aria-hidden="true"></i>
<span ng-bind-html="'${Cart}'"></span>
<span ng-if="cartItemCount > 0" class="label label-as-badge label-primary sp-navbar-badge-count">{{cartItemCount}}</span>
</a>
</li>
<script>
<div ng-click="toggleCart()" class="item-added-tooltip">${Item has been added to your cart.}</div>
</script>
</ul>
Angular template - itscMenuTemplate
<a ng-if="item.items.length == 0 && !item.scriptedItems" ng-href="{{item.href}}" target="{{item.url_target}}">{{ 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="'itscMenuTemplate'" />
</ul>
<a ng-if="item.scriptedItems.count > 0" 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>
<itsc-sp-dropdown-tree ng-if="item.scriptedItems.count > 0" items="item.scriptedItems.items" />
Angular template - itscSpDropdownTreeTemplate
<a ng-if="mi.type == 'link'" title="{{mi.title}}" target="{{mi.target}}" href="{{mi.href}}">
{{mi.title | characters:60}}
</a>
<a ng-if="mi.type == 'record' && !mi.__page" title="{{mi.short_description}}" href="?id=ticket&table={{mi.__table}}&sys_id={{mi.sys_id}}">
<span>{{mi.short_description | characters:60}}</span>
<span class="block color-primary text-muted">
<span class="block" style="float: right">
<sn-time-ago timestamp="mi.sys_updated_on" />
</span>
{{mi.number}}
</span>
</a>
<a ng-if="mi.type == 'record' && mi.__page" title="{{mi.short_description}}" href="?id={{mi.__page}}&table={{mi.__table}}&sys_id={{mi.sys_id}}">
<span>{{mi.short_description | characters:60}}</span>
<span class="block color-primary text-muted">
<span class="block" style="float: right">
<sn-time-ago timestamp="mi.sys_updated_on" />
</span>
{{mi.number}}
</span>
</a>
<a ng-if="mi.type == 'request'" title="{{mi.short_description}}" href="?id=sc_request&table={{mi.__table}}&sys_id={{mi.sys_id}}">
<span>{{mi.short_description | characters:60}}</span>
<span class="block color-primary text-muted">
<span class="block" style="float: right">
<sn-time-ago timestamp="mi.sys_updated_on" />
</span>
{{mi.number}}
</span>
</a>
<a ng-if="mi.type == 'approval'" title="{{mi.short_description}}" href="?id=approval&table={{mi.__table}}&sys_id={{mi.sys_id}}">
<span ng-if="mi.short_description">{{mi.short_description | characters:60}}</span>
<span class="block color-primary text-muted">
<span class="block" style="float: right">
<sn-time-ago timestamp="mi.sys_updated_on" />
</span>
{{mi.number}}
</span>
</a>
<a ng-if="mi.type == 'menu' && mi.items.length" title="{{mi.title}}" href="javascript:void(0)" class="menu_trigger right-caret">
{{mi.title | characters:60}}
</a>
<itsc-sp-dropdown-tree ng-if="mi.type == 'menu' && mi.items.length" items="mi.items" />
Angular provider - type Directive - itscSpDropdownTree
/*! RESOURCE: /scripts/app.$sp/directive.spDropdownTree.js */
function () {
return {
restrict: 'E',
scope: {items: '='},
replace: true,
template: '<ul class="dropdown-menu">' +
'<li ng-repeat="mi in items" style="min-width: 20em;" ng-class="{\'dropdown-submenu\': mi.type == \'menu\', \'dropdown-menu-line\':$index < items.length - 1}" ng-include="getURL()">' +
'</ul>',
link : function(scope, element, attrs, controller) {
scope.getURL = function() {
return 'itscSpDropdownTreeTemplate';
}
}
}
};
(function($) {
$("body").on( "click", "a.menu_trigger", function(e) {
var current = $(this).next();
var grandparent = $(this).parent().parent();
if ($(this).hasClass('left-caret') || $(this).hasClass('right-caret'))
$(this).toggleClass('right-caret left-caret');
grandparent.find('.left-caret').not(this).toggleClass('right-caret left-caret');
current.toggle();
$(".dropdown-menu").each(function(i, elem) {
var elemClosest = $(elem).closest('.dropdown');
var currentClosest = current.closest('.dropdown');
if (!elem.contains(current[0]) && elem != current[0] && (!currentClosest.length || !elemClosest.length || elemClosest[0] == currentClosest[0]))
$(elem).hide();
})
e.stopPropagation();
});
$("body").on( "click", "a:not(.menu_trigger)", function() {
var root=$(this).closest('.dropdown');
root.find('.left-caret').toggleClass('right-caret left-caret');
});
})(jQuery);
;
Thanks,
Shannon
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-10-2017 08:13 AM
just use the following in your itscSpDropdownTree directive and remove the rest..
*****************************************************************
/*! RESOURCE: /scripts/app.$sp/directive.spDropdownTree.js */
function () {
return {
restrict: 'E',
scope: {items: '='},
replace: true,
template: '<ul class="dropdown-menu">' +
'<li ng-repeat="mi in items" style="min-width: 20em;" ng-class="{\'dropdown-submenu\': mi.type == \'menu\', \'dropdown-menu-line\':$index < items.length - 1}" ng-include="getURL()">' +
'</ul>',
link : function(scope, element, attrs, controller) {
scope.getURL = function() {
return 'itscSpDropdownTreeTemplate'
};
}
};
}
*****************************************************************
the following is a screenshot of my own custom dropdownTree directive:

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-10-2017 08:21 AM
It does the same thing with that code as well - it looks like it's thinking for a while and then changes the menu black with the only option being the cart (which won't allow me to click on it - or on any of the links on the rest of the page either). That's in Chrome. In IE, it just freezes the page completely and I need to end the task.
Shannon