Blog

Clone the Header Widget

If you are trying to clone the “Header Menu” widget to make modifications, you’ll notice it isn’t so easy. This article takes through the obstacles of cloning that widget. If this worked for you, let’s hear it in the comments!

Clone Header Widget

  1. Login as admin

  2. Left Navigator Bar > Service Portal Menus > Pick your Menu

  3. Open Widget: Header Menu.

  4. Click the Clone Widget button

  5. Rename to Header Menu v2

  6. On this line of HTML change the ng-include="'menuTemplate'" to ng-include="'menuTemplateCustom'"

<li ng-repeat="item in visibleItems" ng-class="{dropdown: item.items.length > 0, 'header-menu-item': true}" ng-include="'menuTemplateCustom'" role="presentation"></li>

7. Click Update

Copy Angular Templates

The angular templates don’t copy when you clone a Header Menu widget. You can find angular templates at the bottom of the form.

  1. Left Navigator Bar > Service Portal > Widgets

  2. Search and find the old Header Widget: Header Menu

  3. Open each Angular Template at the bottom of the form

  4. Rename the ID and Widget and click INSERT AND STAY

  • ID: menuTemplateCustom | Widget: Header Menu v2

  • ID: item-added-tooltipCustom.html | Widget: Header Menu v2

  • ID: spDropdownTreeTemplateCustom | Widget: Header Menu v2

Directive

You need to add a directive as a there is a new template

  1. Left Navigator Bar > Service Portal > Angular Providers

  2. Click New

  3. Add Code:

Directive: spDropdownTreeTemplateCustom
Script: 
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 'spDropdownTreeTemplateCustom';
			}
		}
	}
};
(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);

4. Click Update

Add Provider

  1. Left Navigator Bar > Service Portal > Widgets

  2. Search and find the new Header Widget: Header Menu v2

  3. At the bottom of form, Click the Angular Provider Related List

  4. Click Edit

  5. Add the provider, spDropdownTreeTemplateCustom

  6. Click Save

Modify Templates

  1. Left Navigator Bar > Service Portal > Widgets

  2. Search and find the new Header Widget: Header Menu v2

  3. At the bottom of form, Click the Angular ng-templates Related List

In the new templates you created, spDropdownTreeTemplateCustom and menuTemplateCustom. Modify lines of code

menuTemplateCustom

<li ng-repeat="item in item.items" ng-include="'menuTemplateCustom'" />

<sp-dropdown-tree-template-custom role="menu" aria-label="{{::item.label}}" ng-if="item.scriptedItems.count > 0" items="item.scriptedItems.items" />

spDropdownTreeTemplateCustom

<sp-dropdown-tree-template-custom ng-if="mi.type == 'menu' && mi.items.length" items="mi.items" />

Add Header Menu v2 to your Menu

Add your new Header Menu v2 widget to the menu of your choice.

Test

If you receive an error on load, or the menu doesn’t load correctly. Likely you missed a step in the instructions above.