Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

Header menu on new Service portal

Chad31
Mega Expert

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.

</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.

9 REPLIES 9

hsafi1
Kilo Contributor

Shannon Burns
Kilo Sage

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


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:


Picture1.png


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