- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-06-2022 10:18 AM - edited 10-06-2022 10:20 AM
We had a request to resolve an issue with a search that is tied to a Service Portal widget we created.
The widget has a Search bar that is using angular js. It searches through the items on the page you're on.
The gr query and pagination is happening on the server side.
If we get rid of the page management that happens on the server side and just run the complete query. The search can then look through all of the items. We can set a limit with angular but this breaks the page functionality.
We're needing to figure out a way to handle pagination on the html side so that we can run the full query and the search input can find items on all of the pages?
HTML Template: (This shows the input we're using for our search and ng-repeat items for our table)
<div ng-if="data.list.length">
<div class="input-group">
<div class="input-group-addon">
<i class="fa fa-search"/>
</div>
<input aria-label="filter" type="text" class="form-control" placeholder="Search" ng-model="search_project">
</div>
<br/><br/>
<table class="table table-striped table-responsive" >
<thead>
<tr>
<th ng-repeat="field in data.fields_array track by $index" class="text-nowrap" ng-click="setOrderBy(field)"
scope="col" role="columnheader" aria-sort="{{field == data.o ? (data.d == 'asc'? 'ascending': 'descending') : 'none'}}">
<div class="th-title" title="${Sort by} {{field == data.o ? (data.d == 'asc' ? '${Descending}': '${Ascending}') : '${Ascending}'}}" role="button" tabindex="0" aria-label="{{data.column_labels[field]}}">{{data.column_labels[field]}}</div>
<i class="fa" ng-if="field == data.o" ng-class="{'asc': 'fa-chevron-up', 'desc': 'fa-chevron-down'}[data.d]"></i>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in data.list | filter:search_project track by item.sys_id" >
<td role="cell" class="pointer sp-list-cell" ng-class="{selected: item.selected}" ng-click="go(item.targetTable, item)" ng-repeat="field in ::data.fields_array" data-field="{{::field}}" data-th="{{::data.column_labels[field]}}">
<span ng-if="$first" aria-label="${Open record}: {{::item[field].display_value}}" role="link" tabindex="0">{{::item[field].display_value | limitTo : item[field].limit}}{{::item[field].display_value.length > item[field].limit ? '...' : ''}}</span>
<span ng-if="!$first">{{::item[field].display_value | limitTo : item[field].limit}}{{::item[field].display_value.length > item[field].limit ? '...' : ''}}</span>
</td>
</tr>
</tbody>
</table>
<div ng-class="{'pruned-msg-filter-pad': (!options.show_breadcrumbs || !data.filter) && !data.list.length}" class="pruned-msg" ng-if="rowsWerePruned()">
<span ng-if="rowsPruned == 1">${{{rowsPruned}} row removed by security constraints}</span>
<span ng-if="rowsPruned > 1">${{{rowsPruned}} rows removed by security constraints}</span>
</div>
</div>
<!-- footer -->
<div class="panel-footer" ng-hide="options.hide_footer" ng-if="data.row_count">
<div class="btn-toolbar m-r pull-left">
<div class="btn-group">
<a ng-disabled="data.p == 1" href="javascript:void(0)" ng-click="setPageNum(data.p - 1)" class="btn btn-default" aria-label="${Previous page} {{data.p == 1 ? '${disabled}' : ''}}" tabindex="{{(data.p == 1) ? -1 : 0}}"><i class="fa fa-chevron-left"></i></a>
</div>
<div ng-if="data.num_pages > 1 && data.num_pages < 20" class="btn-group">
<a ng-repeat="i in getNumber(data.num_pages) track by $index" ng-click="setPageNum($index + 1)" href="javascript:void(0)" ng-class="{active: ($index + 1) == data.p}" type="button" class="btn btn-default" aria-label="${Page} {{$index + 1}}">{{$index + 1}}</a>
</div>
<div class="btn-group">
<a ng-disabled="data.p == data.num_pages" href="javascript:void(0)" ng-click="setPageNum(data.p + 1)" class="btn btn-default" aria-label="${Next page} {{data.p == data.num_pages ? '${disabled}' : ''}}" tabindex="{{(data.p == data.num_pages) ? -1 : 0}}"><i class="fa fa-chevron-right"></i></a>
</div>
</div>
<div class="m-t-xs panel-title">${Rows {{data.window_start + 1}} - {{ mathMin(data.window_end,data.row_count) }} of {{data.row_count}}}</div>
Server Script piece containing the gr query execution and how page management is being handled.
data.filter = gr.getEncodedQuery();
if (data.relationship_id) {
var rel = GlideRelationship.get(data.relationship_id);
var target = new GlideRecord(data.table);
var applyTo = new GlideRecord(data.apply_to);
applyTo.get("sys_id", data.apply_to_sys_id);
rel.queryWith(applyTo, target); // put the relationship query into target
data.exportQuery = target.getEncodedQuery();
gr.addEncodedQuery(data.exportQuery); // get the query the relationship made for us
}
if (data.exportQuery)
data.exportQuery += '^' + data.filter;
else
data.exportQuery = data.filter;
data.exportQueryEncoded = encodeURIComponent(data.exportQuery);
if (data.o){
if (data.d == "asc")
gr.orderBy(data.o);
else
gr.orderByDesc(data.o);
if (gs.getProperty("glide.secondary.query.sysid") == "true")
gr.orderBy("sys_id");
}
data.window_start = data.page_index * data.window_size;
data.window_end = (data.page_index + 1) * data.window_size;
gr.chooseWindow(data.window_start, data.window_end);
gr._query();
data.row_count = gr.getRowCount();
data.num_pages = Math.ceil(data.row_count / data.window_size);
data.column_labels = {};
data.column_types = {};
data.fields_array = data.fields.split(',');
data.headers_array = data.headers.split(',');
// use GlideRecord to get field labels vs. GlideRecordSecure
for (var i in data.fields_array) {
gs.log("Headers copied: "+data.headers_array[i]);
var field = data.fields_array[i];
var ge = grForMetaData.getElement(field);
if (ge == null)
continue;
data.column_labels[field]=data.headers_array[i];
// data.column_labels[field] = ge.getLabel();
data.column_types[field] = ge.getED().getInternalType();
}
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-06-2022 11:09 AM
Hi,
I would do the counting etc client side, and then the filter will work accordingly when you use "uib-pagination". I have attached a working example on knowledge articles. Import it to a dev instance and get it on a test page or something.
I hope you can get the idea of how you can get pagination to work quite smoothly and with less code.
Best regards,
Sebastian Laursen
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-06-2022 11:09 AM
Hi,
I would do the counting etc client side, and then the filter will work accordingly when you use "uib-pagination". I have attached a working example on knowledge articles. Import it to a dev instance and get it on a test page or something.
I hope you can get the idea of how you can get pagination to work quite smoothly and with less code.
Best regards,
Sebastian Laursen