ServicePortal breadcrumb widget

emyrold
Giga Expert

There are a few posts on the community about getting the breadcrumb widget to work with custom pages.  Many of them suggest cloning the widget and then building recursive logic to build the breadcrumbs to your custom pages.  I just took the 2-day service portal advance course at K18 and in the guide it says:

Built-in functionality exists baseline that allows you to overwrite Portal breadcrumbs. Notice the breadcrumbs Widget is always listening for the sp.update.breadcrumbs event with the statement. If it hears It, the callback function executes.

var deregister = $rootscope.$on("sp.update.breadcrumbs", function(e, list) { 

  c.breadcrumbs = list;

});

 

In this example, the KB Article Page Widget transmits the event using the $broadcast() method. And the the SC Order Guide Widget transmits the event using the $emit method.

// KB Article Page client controller

function ($scope, spUtil, $sce, $rootScope, $timeout) {
	spUtil.setSearchPage('kb');
	$scope.data.text = $sce.trustAsHtml($scope.data.text);
	$timeout(function() {
		$rootScope.$broadcast('sp.update.breadcrumbs', $scope.data.breadcrumbs);
	});
}

 

// KB Article Server Script

var t = data;
data.kb_knowledge_page = $sp.getDisplayValue("kb_knowledge_page") || "kb_view";
var articleGR = GlideRecord("kb_knowledge");
articleGR.get($sp.getParameter('sys_id'));
var recordIsValid = articleGR.isValidRecord();
var canReadArticle = articleGR.canRead();
t.isvalid = recordIsValid && canReadArticle;

if (canReadArticle) {
	articleGR.incrementViewCount(); // update sys_view_count immediately on kb_knowledge record
	var art = new GlideRecord("kb_use");
	if (art.isValid()) {
		art.article = articleGR.getUniqueValue();
		art.user = gs.getUserID();
		art.viewed = true;
		art.insert(); // kb_use records are aggregated to update sys_view_count nightly
		$sp.logStat('KB Article View', "kb_knowledge", articleGR.getUniqueValue(), articleGR.short_description);
	}

	t.category = articleGR.getValue('kb_category');
	t.sys_id = $sp.getParameter('sys_id');
	t.showAttachments = false;
	if (articleGR.display_attachments)
		t.showAttachments = true;
	t.categoryDisplay = articleGR.getDisplayValue('kb_category');
	t.short_description = articleGR.getValue('short_description');
	if (articleGR.getValue('article_type') == 'wiki')
		t.text = GlideWikiModel().render(articleGR.getValue('wiki'));
	else
		t.text = articleGR.getValue('text');
	t.sys_view_count = articleGR.getDisplayValue('sys_view_count');
	t.author = articleGR.getDisplayValue('author');
	t.publishedUtc = articleGR.getValue('published');
	t.number = articleGR.getValue('number');
	if (showStarRating())
		t.rating = articleGR.getValue('rating');
	t.direct = false;
	if (articleGR.direct)
		t.direct = true;

	t.breadcrumbs = [{label: t.short_description, url: '#'}];
	if (!articleGR.kb_category.nil()) {
		var rec = articleGR.kb_category.getRefRecord();
		while (rec.getRecordClassName() == "kb_category") {
			t.breadcrumbs.unshift({label: rec.getDisplayValue(), url: '?id=kb_category&kb_category=' + rec.getUniqueValue()});
			rec = rec.parent_id.getRefRecord();
		}
	}
	t.breadcrumbs.unshift({label: gs.getMessage("Knowledge Base"), url: '?id=' + t.kb_knowledge_page});
}

function showStarRating() {
	if (options.show_star_rating == "Yes")
		return true;

	if (options.show_star_rating == "No")
		return false;

	if (gs.getProperty("glide.knowman.show_star_rating", "true") != "true")
		return false;

	return gs.hasRole(gs.getProperty("glide.knowman.show_star_rating.roles"));
}

 

Can someone help me with building the core logic for a very simple case?

TestPortal

- page1 - OOB Bread crumb widget and a single page widget (wg_page1)

- page2 - OOB Bread crumb widget and a single page widget (wg_page2)

- page3 - OOB Bread crumb widget and a single page widget (wg_page1)

the html template on each page has an href to point to the next html page 1 -> 2 -> 3

When I am on page1 and then click page2 and then page3

Bread crumb should be Home > page1 > page2 > page3 

when I click page2, page three should disappear and home all should disappear.

Question: Am I correctly understanding that the baseline functionality of the breadcrumb widget should support this without having to clone it and then write custom logic?  It is just a matter of making sure the page specific widget is getting the correct data in the server script and then letting the client script $broadcast > $rootScope.$broadcast('sp.update.breadcrumbs', $scope.data.breadcrumbs);

Here is my current page1 widget (wg_page1):

// Server Script
(function() {

	var t = data;
	t.page_id = $sp.getParameter('id');
	
	//t.breadcrumbs = [{label: "default-lable", url: '#'}];
	
	t.breadcrumbs.unshift({label: "Erik-page-lable-1", url: '?id=' + t.page_id});

})();

 

// Client Script

function ($scope, spUtil, $sce, $rootScope, $timeout)  {
  /* widget controller */
  var c = this;
	
	spUtil.setSearchPage('kb');
	
	$scope.data.text = $sce.trustAsHtml($scope.data.text);
	
	$timeout(function() {
		$rootScope.$broadcast('sp.update.breadcrumbs', $scope.data.breadcrumbs);
	});
		
}

 

<div>
<pre>Output: I am on {{data.page_id}}</pre>
</div>

<div><a href="?id=page2">${page2}</a></div>

 

 

 

 
19 REPLIES 19

Hi,

Actually I too have same requirement. So, what I did is

I clone the breadcrumb widget. Then I created option schema.

Label - string type (comma seperated labels)

URL -  string type (comma seperated urls)

 

In cloned breadcrumbs widget I made few changes.

server side:

var page = $sp.getParameter('id');
label = options.label||page;
page_id = options.url||page;
labels =label.split(',');
page_ids = page_id.split(',');

for(var i=0;i<labels.length && i<page_ids.length;i++)
{
data.breadcrumbs.push({label:labels[i],url:"?id="+page_ids[i]});
}

client:

$timeout(function()
					{
		console.log(c.data.breadcrumbs);
		$rootScope.$broadcast("sp.update.breadcrumbs",c.data.breadcrumbs);
		
	//console.log(c.data.breadcrumbs);
			})
	$rootScope.$on("sp.update.breadcrumbs", function(e, list) {		
		console.log(list.url);
		c.breadcrumbs = list;
	});

 

I tried like this. I don't know this is best way or not. If you have any ideas please share your thoughts.

Thanks.

 

ok, let me try this....

what about the existing client script stuff, did you remove it or just add to it?

 

function($scope, $rootScope, spUtil) {
    var c = this;
    c.expanded = !spUtil.isMobile();
    c.expand = function() {
        c.expanded = true;
    };

    var deregister = $rootScope.$on("sp.update.breadcrumbs", function(e, list) {
        c.breadcrumbs = list;
    });

    $scope.$on('$destroy', function() {
        deregister();
    });

}

If you broadcast the event then only breadcrumb widget will work. So that both broadcast and listening to that event are with in same client script.

I'm not following what you just said.  Let me restate my question.

You said you cloned the breadcrumb widget.  When you clone something it makes a copy of the existing item.  The existing breadcrumb has code (what I pasted above).  The server and client script examples you provided for dynamic did not show any of the existing OOB breadcrumb code.

My question is: Did you add your code into the existing bread crumb client script or did you overwrite/replace the OOB code with what you wrote?

And to be clear, I understand we are talking about a new breadcrumb widget, whether you cloned and overwrote, or just clicked new and created a brand new one.