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

My requests and My Open incidents Widgets should have pagination.

Sandeep Bharate
Tera Contributor

In the service portal home page , My requests and My Open incidents Widgets should have pagination instead row count beside that there should be a selection with choices 5,10,15,20,25,30,35,40,45,50. When the user selects 5 it should display 5 records in the widget. When 10 , should show 10 records. Same for the remaining. By default it should be 5 for the both My requests and My Open incidents Widgets.

How to achieve this?

find_real_file.png

9 REPLIES 9

Fery,

Here is the full code of my working example for the "My Past Requests" widget we created.

HTML

<div class="panel panel-{{c.options.color}} b" ng-if="c.always_show ||c.data.list.length">
  <div class="panel-heading" >
    <h4 class="panel-title">{{c.options.title}}</h4>
    <i class="fa fa-filter" aria-hidden="true" tabindex="0" ng-click="c.showFilter = !myreq.showFilter;" title="Show filters for {{c.options.title}}"></i>
    <div ng-show="c.showFilter">
      <input ng-model="c.filterText" sn-focus="c.showFilter" style="color: grey; width: 100%; margin-top: .5em;" placeholder="{{data.filterMsg}}" 
             ng-change="c.setFilteredItems(c.data.list | filter:c.filterText)"> 
    </div>
  </div>
  <div class="list-group" style="max-height: none; overflow-y: auto;">
    <div class="list-group-item" ng-repeat="item in c.currentPageItems"> 
      <a  ng-click="c.onClick($event, item, item.url, {})" href="javascript:void(0)"> 
        <div ng-class="{'l-h-40': !item.secondary_fields.length}">{{item.display_field}}</div>
        <small class="text-muted" ng-repeat="f in item.secondary_fields">
          <span ng-if="!$first"> • </span>
          <span ng-switch="f.type" title="{{::f.label}}">
            <span ng-switch-when="glide_date"><sn-time-ago timestamp="::f.value" /></span>
            <span ng-switch-when="glide_date_time"><sn-time-ago timestamp="::f.value" /></span>
            <span ng-switch-default="">{{f.display_value}}</span>
          </span>
        </small>
      </a>
    </div>
  </div>
  <div class="panel-footer" ng-if="c.options.maximum_entries && c.data.count > c.options.maximum_entries">
    
    <div class="h4 number-show-label panel-title">
      ${Showing items {{ c.start + 1}} - {{c.end}} of {{c.filteredItems.length}}}
    </div>
  
    <nav id="prev-tab-nav" class="pull-right" aria-label="Previous requests and tasks page navigation">
      <ul class="pagination">
        <li>
          <a class="btn btn-default" href="#" aria-label="Previous" ng-disabled="c.currentPage == 1" ng-click="c.setCurrentPage(c.currentPage -1)">
            <span aria-hidden="true">&laquo;</span>
          </a>
        </li>
        <li>
          <a class="btn btn-default" href="#" aria-label="Next" id="prev-tab-next" ng-disabled="c.currentPage == c.numPages" ng-click="c.setCurrentPage(c.currentPage + 1)">
            <span aria-hidden="true">&raquo;</span>
          </a>
        </li>
      </ul>
    </nav>
    
    
    <div class="clearfix"></div>
  </div>
</div>

 

CSS

.panel-heading {
  position: relative;
  > .fa-filter { 
    position: absolute;
    top: 1rem; 
    right: 1rem; 
  }
}

.list-group-item > a {
	display: inline-block;
}
div.number-show-label{display:inline-block;}

#prev-tab-nav > ul {
  margin:0;
}
a[aria-label="Previous"]{margin-right:3px;}

 

CLIENT SCRIPT

function ($location, $rootScope) {	
	var c = this;
	c.filterText = "";
	c.showFilter = false;
	
	c.setFilteredItems = function(items) {
		c.filteredItems = items;
		c.currentPageItems = c.filteredItems.slice(0, c.options.maximum_entries);
		c.currentPage = 1;
		c.numPages = Math.ceil(c.filteredItems.length / c.options.maximum_entries);
		c.start = 0;
		c.end = c.options.maximum_entries < c.filteredItems.length ? c.options.maximum_entries : c.filteredItems.length;
	};
	
	c.setFilteredItems(c.data.list);
	
	c.setCurrentPage = function(pageNum) {
		if (pageNum < 1 || pageNum > c.numPages) return;
		c.start = (pageNum - 1) * c.options.maximum_entries;
		c.end = c.start + 5 < c.filteredItems.length - 1 ? c.start + c.options.maximum_entries : c.filteredItems.length;
		c.currentPageItems = c.filteredItems.slice(c.start, c.end);
		c.currentPage = pageNum;
	};
	
		
	c.onClick = function($event, item, url, action) {
		$event.stopPropagation();
		$event.preventDefault();
		if (url)
			$location.search(url);
		else {
			var evt = {};
			evt.url = url;
			evt.table = c.data.table;
			evt.sys_id = item.sys_id;
			evt.record = item;
			evt.rectangle_id = c.data.sys_id;
			evt.action = action;
			// put out the selection with simple list "sl_" prefix
			$location.search('sl_sys_id', evt.sys_id);
			$location.search('sl_table', evt.table);
			$location.search('spa', 1); // spa means "I've got this"
			$rootScope.$broadcast('$sp.list.click', evt);
		}
	};	
}

 

SERVER SCRIPT

(function() {
	if (!options.maximum_entries)
		options.maximum_entries = 20;
	var gr = new GlideRecordSecure('sc_request'); // does ACL checking for us
	//gr.addActiveQuery();
	gr.addQuery('active', false);
	options.title = options.title || gr.getPlural();
	data.display_field = 'sys_created_on';
	data.secondary_fields = ['number','sys_updated_on'];
	data.filterMsg = gs.getMessage("Filter...");
  var username = gs.getUserID();
	gr.addQuery('requested_for',username).addOrCondition('opened_by',username);
	gr.orderByDesc('sys_created_on');
	gr.query();
	data.count = gr.getRowCount();
	data.list = [];
	var recordIdx = 0;
	while (gr.next()) {
		//if (recordIdx == options.maximum_entries)
			//break;

		var record = {};
		record.sys_id = gr.getValue('sys_id');
		var ritm = new GlideRecord("sc_req_item");
		ritm.addQuery("request", gr.getUniqueValue());
		ritm.query();
		if (ritm.getRowCount() == 0)
			continue;

		if (ritm.getRowCount() > 1)
			record.display_field = gs.getMessage("{0} requested items", ritm.getRowCount());
		else {
			ritm.next();
			record.display_field = ritm.cat_item.getDisplayValue() || ritm.getDisplayValue("short_description");
		}

		record.secondary_fields = [];
		data.secondary_fields.forEach(function(f) {
			record.secondary_fields.push(getField(gr, f));
		});

		record.url = {id: 'sc_request', table: 'sc_request', sys_id: record.sys_id};
		data.list.push(record);
		recordIdx++;
	}

	function getField(gr, name) {
		var f = {};
		f.display_value = gr.getDisplayValue(name);
		f.value = gr.getValue(name);
		var ge = gr.getElement(name);
		f.type = ge.getED().getInternalType()
		f.label = ge.getLabel();
		return f;
	}
	
})()

 

I hope this helps.

Seth

Hi,

I am getting a error in the HTML part href = "#" cannot be used it seems.

Are you editing the widget in the Now Platform or the Portal Widget Editor? Also, which version are you running?

I did in Now Platform. I am on Jakarta version

The Now Platform editor gives false errors.  Make your changes using the Portal Widget Editor.  It's a much better interface.  Let me know how it goes.