Embedding knowledge article as Widget in Catalog Item

Jake Golden
Tera Expert

hello,

 

Needing some help on trying to enhance a solution to the thread posted below:

Embedded Knowledge Article in Catalog Item (servicenow.com)

 

In that post - A widget is created and placed inside a catalog item to display a defaulted knowledge article.

 

What I am trying to accomplish is to create a widget that can be dynamic.

 

I currently have 3 choices in my catalog item. Category, SubCategory, and issue. Once these fields are selected a knowledge article number is populated on the catalog item. 

Code below:

Client Script:

function onChange(control, oldValue, newValue, isLoading) {
    if (!isLoading && newValue) {
        var category = g_form.getValue('category');
        var subcategory = g_form.getValue('subcategory');

        var kbGa = new GlideAjax('KB_Data_Utils');
        kbGa.addParam('sysparm_name', 'getKBID');
        kbGa.addParam('sysparm_cat', category);
        kbGa.addParam('sysparm_sub_cat', subcategory);
        kbGa.addParam('sysparm_issue', newValue);
        kbGa.getXMLAnswer(populateKBID);
    }

    function populateKBID(answer) {
        if (answer) {
            g_form.setValue('u_knowledge_article', answer);
        } else {
            g_form.setValue('u_knowledge_article', '');
        }
    }
}

 

 

Client Callable Script Include:

 

var KB_Data_Utils = Class.create();
KB_Data_Utils.prototype = Object.extendsObject(AbstractAjaxProcessor, {

    getKBID: function() {
		var category = this.getParameter('sysparm_cat');
		var subcategory = this.getParameter('sysparm_sub_cat');
		var issue = this.getParameter('sysparm_issue');
		
        var kbArticle = new GlideRecord('kb_knowledge');
        kbArticle.addQuery('u_knowledge_base', "General");
        kbArticle.addQuery('category', category);
        kbArticle.addQuery('u_subcategory', subcategory);
        kbArticle.addQuery('u_issue', issue);
        kbArticle.query();
        if (kbArticle.next()) {
            return kbArticle.sys_id + '';
        }
        return '';
    },

    type: 'KB_Data_Utils'
})

 

 

Somehow I would like to replicate the above code into the example post from above. Not sure where to start.

 

thanks,

Jake

 

1 ACCEPTED SOLUTION

AnveshKumar M
Tera Sage
Tera Sage

Hi @Jake Golden ,

You can keep the existing code as is and extend the catalog to display the KB in widget. I just tweaked the actual widget you referenced in your question. Follow along to get it.

Create a widget with the following scripts,

Name: Embedded KB Article

ID: embedded_kb_article

Body HTML Template: 

 

<div ng-if="data.isArticle" class="articleContainer">

    <!-- Shows the article's title - You can remove this line if you don't want to show this -->
    <h3 ng-bind-html="data.articleTitle"></h3>

    <!-- This line loads the article's HTML into the body of this widget -->
    <div ng-bind-html="data.articleHTML"></div>

</div>

 

 

CSS:

 

.articleContainer {
  overflow:scroll;
  max-height: 500px;
  border: 1px solid #DDDDDD;
  border-radius: 5px;
  padding: 16px;
}

 

 

Server Script:

 

(function() {	
	// Only run the below after the client controller calls this. Reason: Catalog item loads quicker & the script below requires the variable_name loaded in the page
	data.isArticle = false;
	if(input) { 

		var article = new GlideRecord('kb_knowledge');  // Initiate a glide record object (knowledge article table)
			article.addQuery('number', input.kbNumber);      // The KB number corresponds to the default value set in this variable of the record producer
			article.addQuery('workflow_state', 'published');// The KB article should be in the published state to be shown to end-users
			article.query();                                // Execute the query

			if(article.next()) { // If an article is found, show the article
				data.articleTitle = article.getDisplayValue('short_description').toString();               // Capture the title of the article
				data.articleHTML  = article.text.toString().replace('<![CDATA[ ', '').replace(' ]]>', ''); // Capture & clean the body HTML of the article
				data.isArticle = true;
			} else {             // If an article is not found, display the below message
				data.articleHTML = '<p>Article ' + data.kbNumber + ' missing or out-dated. Please contact support.<p>';
			}
	}
})();

 

 

Client Script:

 

api.controller = function($scope, $rootScope, $timeout) { // REMEBER to add $scope in the parameter list here (not in by default)
	var c = this;
	
	$rootScope.$on("field.change", function(evt, parms){
		if(parms.field.name == 'u_knowledge_article'){
			var kb_num = parms.field.value;
			if(kb_num){
				$scope.data.kbNumber = parms.field.value;
				c.server.update();
			}
		}
	});
	
};

 

 

Save the widget.

 

Change the client Callable script include to return the number instead of sys_id.

 

var KB_Data_Utils = Class.create();

KB_Data_Utils.prototype = Object.extendsObject(AbstractAjaxProcessor, {

 

    getKBID: function() {

  var category = this.getParameter('sysparm_cat');

  var subcategory = this.getParameter('sysparm_sub_cat');

  var issue = this.getParameter('sysparm_issue');

  

        var kbArticle = new GlideRecord('kb_knowledge');

        kbArticle.addQuery('u_knowledge_base', "General");

        kbArticle.addQuery('category', category);

        kbArticle.addQuery('u_subcategory', subcategory);

        kbArticle.addQuery('u_issue', issue);

        kbArticle.query();

        if (kbArticle.next()) {

            return kbArticle.number + '';

        }

        return '';

    },

 

    type: 'KB_Data_Utils'

})

Create a custom field in the catalog and set the widget field to the one we created in previous steps (you can refere the original article you referenced for this step), you can make the u_knowledge_article field to hidden, but don't delete it.

 

Now try filling all three fields and the KB will be previewed.

 

 

Thanks,
Anvesh

View solution in original post

5 REPLIES 5

@Jake Golden  Great! I could be of help 🙂

Thanks,
Anvesh