The CreatorCon Call for Content is officially open! Get started here.

How to get the KB Category Page widget to sort the Knowledge Articles based on the Short Description

jlaue
Mega Sage

Hello - 

When I use the KB - Categories - KBv3 Widget in Service Portal and click on a specific Knowledge Base category, it appears to be sorting the articles on the articles category, on the KB Category Page widget.  I was wondering if there was a way that I could get these articles to sort/order on the Short Description of the Knowledge Article instead of the current way it is sorting. 

I am not sure if this sort is controlled in the KB Categories - KBv3 widget or if it is happening in the KB Category Page widget, and how I can update this.  The SC Categories widget and SC Category Page widget are properly sorting on the name of the Catalog Item, I was hoping to achieve a similar result with the KB widgets.  

Thanks!

1 ACCEPTED SOLUTION

Jack
Tera Guru

Hi @jlaue,

This is my way:

  1. Clone KB Category Page widget (example: KB Category Page v1.0)
  2. Update HTML code as below:
    <div>
      <div ng-if="data.categoryExists" class="panel panel-{{::options.color}} b">
        <div class="panel-heading">
          <h2 class="panel-title">{{data.categoryDisplay}}</h2>
        </div>
    
        <div role="list" class="panel-body">
          <div ng-if="data.items.length == 0">
            (${No articles})
          </div>
          <div role="listitem" ng-repeat="kb_article in data.items  | orderBy : 'title'" class="sp-kb-topic-article m-b-lg">
              <a ng-href="?id=kb_article&sys_id={{::kb_article.sys_id}}">{{::kb_article.title}}</a>
            <div style="max-height: 3em; overflow: hidden; padding-top:4px;" aria-label="{{::c.getShortenText(kb_article.text)}}">{{::kb_article.text}}</div>
            <div class="kb-about" style="padding-top:4px;">
              <span class="about-outer-span">
                <span class="author pad-right" ng-if="kb_article.author">
                  <glyph sn-char="user" class="pad-right" aria-hidden="true"/>
                  ${Authored by {{::kb_article.author}}}
                </span>
                <span ng-if="kb_article.sys_view_count == 1" class="views pad-right">
                  <span class="pad-right">&#8226;</span> <glyph sn-char="eye-open" class="pad-right" />
                  ${{{::kb_article.sys_view_count}} View}
                </span>
                <span ng-if="kb_article.sys_view_count > 1" class="views pad-right">
                  <span class="pad-right">&#8226;</span> <glyph sn-char="eye-open" class="pad-right" />
                  ${{{::kb_article.sys_view_count}} Views}
                </span>
                <span class="published pad-right">
                  <span class="pad-right" aria-hidden="true">&#8226;</span> <glyph sn-char="calendar" class="pad-right" aria-hidden="true" />
                  <sn-day-ago date="kb_article.published"/>
                </span>
                <span ng-if="data.showStarRating && kb_article.rating">
                  <span class="pad-right">&#8226;</span> <uib-rating ng-model="::kb_article.rating" max="5" readonly="true" aria-label="${Article rating} - ${Read Only}"/>
                </span>
              </span>
            </div>
          </div>
        </div>
    
      </div>
    
    </div>​

    Note: my idea is using orderBy of AngularJS
    <div role="listitem" ng-repeat="kb_article in data.items  | orderBy : 'title'" class="sp-kb-topic-article m-b-lg">

  3. Go to  kb_category page and replace OOB widget by new widget

And this is the result.

Hope this will help.

 

 

 

View solution in original post

16 REPLIES 16

Carl Fransen1
Kilo Sage

Hi All,

I know there is a solution for this, but yesterday I found another solution as well, slightly shorter.

We still update the OOTB widget 'KB Category Page' to create a copy and re-point your container to the new widget. 

In the 'Client Controller' script just add lines 6-9 to the script, the section that starts with the comment, see below:

 

function ($scope, $rootScope, $timeout, spKBCategoryService) {
	var accessWordCountMax = 15;
	var c = this;
	init();
	
	// opus change - sort documents by title name
	c.data.items.sort(function (a, b) {
		return a.title.localeCompare(b.title);
	});
	
	c.getShortenText = function getShortenText(text) {
		var wordsArray = text.split(" ");
		if (wordsArray.length > accessWordCountMax)
			wordsArray = wordsArray.slice(0, accessWordCountMax);
		return wordsArray.join(" ");
	}

 

and that's it, works great!

I'm trying to get this working on the 'server script' so it's not run on the client side, if I find a solution I'll update this thread.

 

Hope this helps someone.

ALso Seth assisted me with code to get the Category sort working on the 'Server Script' so it doesn't run on the client side.

Check out the community article below:

https://community.servicenow.com/community?id=community_question&sys_id=f1838365dbd8dbc01dcaf3231f96...

 

Cheers

Carl.

I have a slightly better solution - this runs on the server script, not the client controller, so it runs server side and won't impact the client loading times.

 

Server script for 'KB Category Page' is:

//CJF 17-05-18 Opus - Updated code to sort documents by title to run server side
  data.items.sort(function(a,b) {
		// below code works, but localCompare will work for all locales/languages
	  //return (a.title.toLowerCase() > b.title.toLowerCase()) ? 1 : ((b.title.toLowerCase() > a.title.toLowerCase()) ? -1 : 0);
	  return a.title.localeCompare(b.title);
	});

both lines starting with 'return' will work, but as per the comments the localCompare provides more handling cases for language/locale.

Server script for 'KB Categories V3' is:

//CJF 17/05/18 Opus new code to sort the Categories alphabetically by label name
	data.categories.sort(function(a,b) {
		// below code works, but localCompare will work for all locales/languages
		   //return (a.label.toLowerCase() > b.label.toLowerCase()) ? 1 : ((b.label.toLowerCase() > a.label.toLowerCase()) ? -1 : 0);
		return a.label.localeCompare(b.label);
	});

 

Hope this helps!

 

 

Hi @Carl Fransen,

Your solution is good performance, and I agree array should be sorted at server-side instead of client-side.

I have enhanced code for this widget:

  1. Clone KB Category Page widget (example: KB Category Page v1.0)
  2. Update Server-script code as below (append code):
    /****************sorting list article**********************/
    data.sortBy = options.sortBy || "short_description";
    data.sortDesc = options.sortDesc == "true" || false;
    
    data.items = sortArticles(data.items,data.sortBy,data.sortDesc);
    
    function sortArticles(arr,field,desc){
    	try{
    		arr.sort(function(a, b) {
    			var compare = a[field].localeCompare(b[field]);
    			if(desc){
    				if(compare == 1){
    					compare = -1;
    				}
    				else{
    					compare = 1;
    				}
    			}
    			return compare;
    		});
    	}catch(err){
    		console.log("***ERROR: " + err);
    	}
    	return arr;
    }​
  3. Go to  kb_category page and replace OOB widget by new widget
  4. Open instance widget and add some options:
    find_real_file.png
    Note: currently, sort method is only supported for string
    "sortBy" {String}: field name which you want to sort (example: number,title,short_description...)
    "sortDesc" {Bool}: 'true' if you want to desc sort

 

Hope this is useful.

jlaue
Mega Sage

Hi Jack/Carl - 

 

I was wondering if one of you would be able to help me with a similar issue with a different widget.  I posted this on:

 

https://community.servicenow.com/community?id=community_question&sys_id=9e5dbfc4dbde57004816f3231f96...

 

Thanks so much!!

 

J