How to customize Data Table widget to make it show True/False as checkbox and editable by clicking?

Aki18
Tera Contributor

On Service Portal, we would like to make the Data Table widget show the "True/False" field as checkbox and editable by just clicking on it, but not sure about how to customize the widget. Can it be achieved by editing HTML/CSS or server script?

Could someone please advise me on how to customize the cloned widget to meet the requirements?

 

Aki18_0-1686126592169.png

 

Best Regards,

Aki

1 ACCEPTED SOLUTION

Hm what could also be, is that the GlideAjax's callback is actually executed before the record watcher callback. This would explain the strange delay...

I would assume you can improve the behavior by not relying on the recordwatcher anymore and just apply the changed value by your own:

1.) In the Client Callable Script Include, return the new value for your field, e.g.:

var ListEditUtils = Class.create();
ListEditUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {
	
	toggleItem: function () {
		var inc = new GlideRecord('incident');
		if (inc.get(this.getParameter('item'))) {
			inc.active = !inc.active;
			inc.setWorkflow(false);
			inc.update();
			return inc.active.toString(); // return the new value
		}
		
		return 'false';
	},

    type: 'ListEditUtils'
});

2.) In the client controller, modify the c.click like this (to apply the updated field value on your own, of course you wont be using the active field - so please modify the script as you would also for the script include above):

// ...
	c.click = function (item) {		
		var ga = new window.GlideAjax('global.ListEditUtils');
		ga.addParam('sysparm_name', 'toggleItem');
		ga.addParam('item', item.sys_id);
		ga.getXMLAnswer(function (result) {
			item.active.display_value = result;
			tableScope.$apply(); // rerender the table
		});
	};
//...

View solution in original post

13 REPLIES 13

Markus Kraus
Kilo Sage

Hi, you have multiple ways of getting this to work without cloneing the widget:

  1. Store Application: Swiss Tool (enables you to display HTML fields)
  2. Inject a dependency (which accomplishes the same result as cloning a widget - but without having to actually clone the widget): [HowTo] Add Buttons on Data Tables (no OOTB artifact changes needed)

Hi @Markus Kraus ,

Thank you so much for the great widget, but is it for adding a button to the Data Table list?

I could successfully add the [X] button by associating your widget with my "data table from URL definition" widget, but I would like the list to show "True/False" field as checkbox and editable by just clicking on it.

Do you have any ideas to modify your great widget to meet my requirements?

Aki18
Tera Contributor

Hi @Markus Kraus ,

I addition to my question above, could you please let me know how to update the field value on which the button is clicked as below?

I think that scripting is needed in "c.click = function (item)" part of Client Controller, but not sure how to write it. Please kindly give me some advice on that.

 

Aki18_0-1686205399166.png

 

EDIT: BTW: The record watcher is not working on a data table widget where no filter is set. please keep that in mind if you ever wonder why the table isn't updating even after you added the "two way binding" fix below. 

 

Hehe, unfortunately the data displayed on the OOTB data table widget is "one way" bound, which means it isn't updated when the record changes.

To get around this you have to adjust the HTML replacement a little bit:

 

var template = tableScope.widget.template
	.replace('::item[field]', 'item[field]') // disable two-way binding on widget-data-table
	.replace('</th>', '</th><th>Actions</th>')
	.replace('</td>', '</td><td ng-class="{selected: item.selected}"><button ng-click="click(item)">X</button></td>');

 

 

Next step, in order to update the record effectively you should create a Client Callable GlideAjax which updates the a given record (note: dont forget to check the "client callable" checkbox):

 

/* global Class, GlideRecordSecure */
/* eslint no-undef: "error" */
var SCRIPT_INCLUDE = Class.create();
SCRIPT_INCLUDE.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {

	toggleItem: function () {
		var itemSysID = this.getParameter('item');
		var itemGr = new GlideRecordSecure('incident');
		if (itemGr.get(itemSysID)) {
				itemGr.FIELD = !itemGr.FIELD;
				itemGr.update();
		}
	},

	type: 'ScriptIncludeClient'
});

 

 

The c.click could then look like this:

 

c.click = function (item) {
	var ga = new window.GlideAjax('SCRIPT_INCLUDE').setScope('x_my_scope');
	ga.addParam('sysparm_name', 'MYUPDATEFUNC');
	ga.addParam('item', item.sys_id);
	ga.getXMLAnswer(function (result) {
		// at this point the data table widget should update itself automatically
	});
};

 

 

I haven't tested this code yet, but I've done something very similar a few months ago. The code is mostly copy paste from a buch of scripts i have on my github (https://github.com/kr4uzi)