Custom Field of Catalog Item in Service Catalog Category Table view

gconway
Tera Contributor

 

 

Hi All,

 

we have a requirement to show a custom field and it's value on the service portal in the Table View of the service catalog. Values of the custom field are not showing up in the list/table.

Back-end view:

gconway_0-1678528111421.png

 

 

SP View:

gconway_1-1678528145682.png

Steps so far:

  1. created custom field on the Catalog Item / Table in the back-end. (The custom field is of the Translated Text type)
  2. cloned the sc_category page to allow customizing
  3. changed Server Script to this:

 

 

 

	function fetchItemDetails(itemRecord, items) {
		while (itemRecord.next()) {
				var catalogItemJS = new sn_sc.CatItem(itemRecord.getUniqueValue());
				if (!catalogItemJS.canView())
					continue;
				var catItemDetails = catalogItemJS.getItemSummary();
				var item = {};
				item.name = catItemDetails.name;
				item.short_description = catItemDetails.short_description;
				item.u_custom_field = catItemDetails.u_custom_field; //<- THIS IS MY CUSTOM FIELD
				item.picture = catItemDetails.picture;
				item.price = catItemDetails.price;
				item.sys_id = catItemDetails.sys_id;
				item.hasPrice = catItemDetails.show_price;
				item.page = 'sc_cat_item';
				item.type = catItemDetails.type;
				item.order = catItemDetails.order;
				item.sys_class_name = catItemDetails.sys_class_name;
				item.titleTag = catItemDetails.name;
				if (item.type == 'order_guide') {
					item.page = 'sc_cat_item_guide';
				} else if (item.type == 'content_item') {
					item.content_type = catItemDetails.content_type;
					item.url = catItemDetails.url;
					if (item.content_type == 'kb') {
						item.kb_article = catItemDetails.kb_article;
						item.page = 'kb_article';
					} else if (item.content_type == 'external') {
						item.target = '_blank';
						item.titleTag = catItemDetails.name + " ➚";
					}
				}
				items.push(item);
			}
	}

 

 

 

 

  • and changed HTML code to this:

 

 

 

      <div id="tabpanel-grid-{{::data.category_id}}" role="tabpanel" aria-labelledby="{{'tab-grid'}}" ng-if="view == 'grid' && data.items.length > 0">
        <table class="table table-striped item-table" aria-label="{{::data.category.title}}" aria-describedby="id-caption-category">
        	<caption id="id-caption-category"><span class="sr-only">{{::data.category.title}}</span></caption>
          <thead>
            <tr>
              <th id="id-header-item" scope="col" colspan="2">${Item}</th>
              <th id="id-header-description" scope="col" colspan="3">${Description}</th>
              <th id="id-header-custom_field" scope="col" colspan="3">${Custom Field}</th> //<-THIS IS THE CUSTOM FIELDS TABLE HEADER
            	<th id="id-header-price" scope="col" ng-if="data.showPrices">${Price}</th>
            </tr>
          </thead>
          <tbody>
            <tr ng-repeat="item in data.items | orderBy: 'order' | limitTo: data.limit track by item.sys_id" ng-init="startItemList()">
              <td id="id-item-{{item.sys_id}}" headers="id-header-item" scope="row" colspan="2">
                <a target="{{::item.target}}" ng-href="{{::getItemHREF(item)}}" sn-focus="{{::item.highlight}}" ng-click="onClick($event, item)"> 
                	<div>
                    <img ng-src="{{::item.picture}}?t=small" ng-if="item.picture" alt="" class="m-r-sm m-b-sm item-image pull-left"/>
                    <span class="catalog-text-wrap catalog-item-name">{{::item.name}}</span>
                    <span ng-if="item.content_type == 'external'"><span class="sr-only">${External Link}</span> ➚</span>
                  </div>
                </a>
            	  </td>
            	  <td headers="id-header-description id-item-{{item.sys_id}}" class="catalog-text-wrap" colspan="3">{{::item.short_description}}</td>
              	<td headers="id-header-u_custom_field id-item-{{item.sys_id}}" class="catalog-text-wrap" colspan="3">{{::item.u_custom_field}}</td> //<- THIS IS WERE THE VALUE OF THE CUSTOM FIELD SHOULD SHOW UP
            	  <td headers="id-header-price id-item-{{item.sys_id}}" ng-if="data.showPrices">{{::item.price}}</td>
            </tr>
          </tbody>
        </table>
      </div>
     

 

 

 

 

Is there anything else I needed to do to make this work? Thank you in advance!

This requirement is the same for the Popular Items View in the service catalog on the Portal.

 

 

#tokyo

 

 

 

5 REPLIES 5

gconway
Tera Contributor

Hi all, 

I solved this myself partially. 

gconway_0-1678383824395.png

 

 

 

 

item.u_custom_field = itemRecord.getDisplayValue('u_custom_field'); //<- This will show the custom field value from the Catalog Item

 

 

 

I now need to find the way to achieve the same for the Popular Items Table View, because the values don't show up. 

gconway_1-1678383919427.png

Anyone have an idea how to change the below script? 

 

 

 

function getPopularItems() {
        return new SCPopularItems().useOptimisedQuery(gs.getProperty('glide.sc.portal.popular_items.optimize', true) + '' == 'true')
            .baseQuery(options.popular_items_created + '')
            .allowedItems(getAllowedCatalogItems())
            .visibleStandalone(true)
            .visibleServicePortal(true)
            .itemsLimit(6)
            .restrictedItemTypes('sc_cat_item_guide,sc_cat_item_wizard,sc_cat_item_content,sc_cat_item_producer'.split(','))
            .itemValidator(function(item, itemDetails) {
                if (!item.canView() || !item.isVisibleServicePortal())
                    return false;

                return true;
            })
            .responseObjectFormatter(function(item, itemType, itemCount) {
                return {
                    order: 0 - itemCount,
                    name: item.name,
                    short_description: item.short_description,
                    u_custom_field: item.u_custom_field, //<-this doesn't work
                    picture: item.picture,
                    price: item.price,
                    sys_id: item.sys_id,
                    hasPrice: item.price != 0,
                    page: itemType == 'sc_cat_item_guide' ? 'sc_cat_item_guide' : 'sc_cat_item'
                };
            })
            .generate();
    }

 

 

 

 

Thank you in advance!

Hi,

Could you make it work as you wanted?

Where exactly did you add this line?

item.u_custom_field = itemRecord.getDisplayValue('u_custom_field'); //<- This will show the custom field value from the Catalog Item

 

Thanks

 

Hi @jose_quinonez ,

 

yes I did. You have to change the server script in 4 places within the SC Category Page (in Widget Editor).

 

1. Under the function fetchItemDetails add:

item.u_custom_field = itemRecord.u_custom_field.getDisplayValue();

 

2. Under the function getPopularItems you have to add this in each "while" loop

item.u_custom_field = count.cat_item.u_custom_field.getDisplayValue();

 

3. Under the var Producers you also have to add the same thing once

item.u_custom_field = count.cat_item.u_custom_field.getDisplayValue();

 

Here is the complete script for your reference. 

 

(function() {
	if (input && input.category_id)
		data.category_id = input.category_id;
	else
		data.category_id = $sp.getParameter("sys_id");
	
	data.error = '';
	data.catalog_id = $sp.getParameter("catalog_id") ? $sp.getParameter("catalog_id") + "" : "-1";
	var catalogsInPortal = ($sp.getCatalogs().value + "").split(",");
	var isCatalogAccessibleViaPortal = data.catalog_id == -1 ? true : false;
	catalogsInPortal.forEach(function(catalogSysId) {
		if (data.catalog_id == catalogSysId) {
			isCatalogAccessibleViaPortal = true;
		}
	});
	data.categorySelected = gs.getMessage('category selected');
	if(!isCatalogAccessibleViaPortal) {
		data.error = gs.getMessage("You do not have permission to see this catalog");
		return;
	}
	var catalogDisplayValue;
	if (data.catalog_id && data.catalog_id !== "-1") {
		var catalogObj = new sn_sc.Catalog(data.catalog_id);
		if (catalogObj) {
			if (!catalogObj.canView()) {
				data.error = gs.getMessage("You do not have permission to see this catalog");
				return;
			}
			catalogDisplayValue = catalogObj.getTitle();
		}
	}
	if (options && options.sys_id)
		data.category_id = options.sys_id;
	data.showPrices = $sp.showCatalogPrices();
	data.sc_catalog_page = $sp.getDisplayValue("sc_catalog_page") || "sc_home";
	data.sc_category_page = $sp.getDisplayValue("sc_category_page") || "sc_category";
	catalogDisplayValue = catalogDisplayValue ? catalogDisplayValue : $sp.getCatalogs().displayValue + "";
	var catalogIDs = (data.catalog_id && data.catalog_id !== "-1") ? data.catalog_id : $sp.getCatalogs().value + "";
	var catalogArr = catalogDisplayValue.split(",");
	var catalogIDArr = catalogIDs.split(",");
	data.sc_catalog = catalogArr.length > 1 ? "" : catalogArr[0];

	data.show_more = false;
	if (GlideStringUtil.nil(data.category_id)) {
		 data.items = getPopularItems();
		 data.show_popular_item = true;
		 data.all_catalog_msg = (($sp.getCatalogs().value + "").split(",")).length > 1 ? gs.getMessage("All Catalogs") : "";
		 data.all_cat_msg = gs.getMessage("All Categories");
		 data.category = {title: gs.getMessage("Popular Items"),
									 description: ''};
		return;
	}

	data.show_popular_item = false;
	// Does user have permission to see this category?
	var categoryId = '' + data.category_id;
	var categoryJS = new sn_sc.CatCategory(categoryId);
	if (!categoryJS.canView()) {
		data.error = gs.getMessage("You do not have permission to see this category");
		return;
	}
	data.category = {title: categoryJS.getTitle(),
	description: categoryJS.getDescription()};

	var catalog = $sp.getCatalogs().value;
	
	data.items = [];
	var itemsInPage = options.limit_item || 999;

	data.limit = itemsInPage;
	if (input && input.new_limit)
		data.limit = input.new_limit;
	if (input && input.items) {
		data.items = input.items.slice();//Copy the input array
	}

	if (input && input.startWindow) {
		data.endWindow = input.endWindow;
	}
	else {
		data.startWindow = 0;
		data.endWindow = 0;
	}

	while (data.items.length < data.limit + 1) {
		data.startWindow = data.endWindow;
		data.endWindow = data.endWindow + itemsInPage;
		var itemGR = queryItems(catalog, categoryId, data.startWindow, data.endWindow);
		if (!itemGR.hasNext())
			break;
		fetchItemDetails(itemGR, data.items);
	}

	if (data.items.length > data.limit)
			data.show_more = true;

	data.more_msg = gs.getMessage(" Showing {0} items", data.limit);

	data.categories = [];
	while(categoryJS && categoryJS.getParent()) {
		var parentId =  categoryJS.getParent();
		categoryJS = new sn_sc.CatCategory(parentId);
		var category = {
			label: categoryJS.getTitle(),
			url: '?id='+data.sc_category_page+'&sys_id=' + parentId
		};
		data.categories.unshift(category);
	}

	data.all_catalog_msg = (($sp.getCatalogs().value + "").split(",")).length > 1 ? gs.getMessage("All Catalogs") : "";

	function fetchItemDetails(itemRecord, items) {
		while (itemRecord.next()) {
				var catalogItemJS = new sn_sc.CatItem(itemRecord.getUniqueValue());
				if (!catalogItemJS.canView())
					continue;
				var catItemDetails = catalogItemJS.getItemSummary(true);
				var item = {};

				item.u_custom_field = itemRecord.u_custom_field.getDisplayValue(); //<-custom row
				item.name = catItemDetails.name;
				item.short_description = catItemDetails.short_description;
				item.picture = catItemDetails.picture;
				item.price = catItemDetails.price;
				item.sys_id = catItemDetails.sys_id;
				item.hasPrice = catItemDetails.show_price;
				item.page = 'sc_cat_item';
				item.type = catItemDetails.type;
				item.order = catItemDetails.order;
				item.sys_class_name = catItemDetails.sys_class_name;
				item.titleTag = catItemDetails.name;
				if (item.type == 'order_guide') {
					item.page = 'sc_cat_item_guide';
				} else if (item.type == 'content_item') {
					item.content_type = catItemDetails.content_type;
					item.url = catItemDetails.url;
					if (item.content_type == 'kb') {
						item.kb_article = catItemDetails.kb_article;
						item.page = 'kb_article';
					} else if (item.content_type == 'external') {
						item.target = '_blank';
						item.titleTag = catItemDetails.name + " ➚";
					}
				}
				items.push(item);
			}
	}

	function queryItems(catalog, categoryId, startWindow, endWindow) {
			var scRecord = new sn_sc.CatalogSearch().search(catalog, categoryId, '', false, options.show_items_from_child != 'true');
			scRecord.addQuery('sys_class_name', 'NOT IN', 'sc_cat_item_wizard');
			scRecord.addEncodedQuery('hide_sp=false^ORhide_spISEMPTY^visible_standalone=true');
			scRecord.chooseWindow(startWindow, endWindow);
			scRecord.orderBy('order');
			scRecord.orderBy('name');
			scRecord.query();
			return scRecord;
	}

	 	
	function getPopularItems (itemRecord, items) {
			var catalog = $sp.getValue('sc_catalog');
			var limit = 106;
			var items = [];
			var itemRecord = [];
			var count = new GlideAggregate('sc_req_item');
			count.addAggregate('COUNT','cat_item');
			count.groupBy('cat_item');
			count.addQuery('cat_item.sys_class_name', 'NOT IN', 'sc_cat_item_guide,sc_cat_item_wizard,sc_cat_item_content');
			count.addQuery('cat_item.sc_catalogs', 'IN', catalog);
			count.addEncodedQuery('cat_item.hide_sp=false^ORcat_item.hide_spISEMPTY');
			count.orderByAggregate('COUNT', 'cat_item');
			count.query();
			while (count.next() && items.length < limit) {
				var catalogItemJS = new sn_sc.CatItem(count.cat_item.sys_id.getValue());
					if (!catalogItemJS.canView() || !catalogItemJS.isVisibleServicePortal())
						continue;
				var item = {};
				var catItemDetails = catalogItemJS.getItemSummary();
				
				item.order = 0 - count.getAggregate('COUNT', 'cat_item');
				item.name = catItemDetails.name;
				item.short_description = catItemDetails.short_description;
				item.u_custom_field = count.cat_item.u_custom_field.getDisplayValue(); //<-custom row
				item.picture = catItemDetails.picture;
				item.price = catItemDetails.price;
				item.sys_id = catItemDetails.sys_id;
				item.hasPrice = item.price != 0;
				item.page = 'sc_cat_item';
				items.push(item);
			}
			
			while (itemRecord.next()) {
				var catalogItemJS = new sn_sc.CatItem(itemRecord.getUniqueValue());
				if (!catalogItemJS.canView())
					continue;
				var catItemDetails = catalogItemJS.getItemSummary();
				var item = {};
				item.name = catItemDetails.name;
				item.short_description = catItemDetails.short_description;
				item.u_custom_field = count.cat_item.u_custom_field.getDisplayValue(); //<-custom row
				item.picture = catItemDetails.picture;
				item.price = catItemDetails.price;
				item.sys_id = catItemDetails.sys_id;
				item.hasPrice = item.price != 0;
				item.page = 'sc_cat_item';
				items.push(item);
			}

			var producers = 0;
			count = new GlideAggregate('sc_item_produced_record');
			count.addQuery('producer.sc_catalogs', 'IN', catalog);
			count.addEncodedQuery('producer.hide_sp=false^ORproducer.hide_spISEMPTY');
			count.addAggregate('COUNT', 'producer');
			count.groupBy('producer');
			count.orderByAggregate('COUNT', 'producer');
			count.query();
			while (count.next() && producers < limit) {
					var catalogItemJS = new sn_sc.CatItem(count.getValue('producer'));
					if (!catalogItemJS.canView() || !catalogItemJS.isVisibleServicePortal())
						continue;
					var catItemDetails = catalogItemJS.getItemSummary();
					var item = {};

					item.order = 0 - count.getAggregate('COUNT', 'producer');
					item.name = catItemDetails.name;
					item.short_description = catItemDetails.short_description;
					item.u_custom_field = count.cat_item.u_custom_field.getDisplayValue(); //<-custom row
					item.picture = catItemDetails.picture;
					item.price = catItemDetails.price;
				    item.hasPrice = item.price != 0;
					item.sys_id = catItemDetails.sys_id;
					item.page = 'sc_cat_item';
					items.push(item);
					producers++;
			}
			return items;
	}

	function getAllowedCatalogItems () {
		var allowedItems = [];
		catalogIDArr.forEach(function(catalogID) {
			var catalogObj = new sn_sc.Catalog(catalogID);
			var catItemIds = catalogObj.getCatalogItemIds();
			for(var i=0; i<catItemIds.length; i++) {
				if (!allowedItems.includes(catItemIds[i]))
					 allowedItems.push(catItemIds[i]);
			}
		});
		return allowedItems;
	}

})();