Set variable ReadOnly when Multi Row Variable Set not empty

SamuelChang
Tera Contributor

Hi all,

 

I need some help or guidance on how to set a variable Read-Only when the Multi Row Variable Sets (MRVS) not empty i.e. once it populated at least one item.


Basically, once I added Report Name & Email the field outside of MRVS should be set to Read-Only

SamuelChang_0-1722362720233.png

 

I've tried onLoad client script but it doesn't work quite right

function onLoad() {
	var mrvs = JSON.parse(g_form.getValue('report_name_and_email'));
	if(mrvs.length > 0) {
		g_form.setReadOnly('add_or_remove', true);
	}
}

Is there something else that I missed?

 

Thank you in advance!

17 REPLIES 17

In the widget script, can you make sure your MRVS variable name is correct?


If my response helped you, please click on "Accept as solution" and mark it as helpful.
- Saloni

Here is my MRVS

SamuelChang_0-1722439401392.png

 

And here is my widget script

SamuelChang_1-1722439439116.png

 

Markus Kraus
Kilo Sage

I think pretty much everyone who ever worked with MRVS wished, that we had a way on the "parent" (the catalog item) to detect a change of a MRVS. All solutions posted (and some even got accepted as a "solution") have flaws:
They either don't work in the classic UI and/or they are built in a way that the does the change-detection every angular-cycle. So I did some tinkering and came up with a solution which works in the Classic UI as well as Service Portal.

Create a new variable of type custom, and make it Hidden=true.
In the 'Type Specification' Section of the new custom variable, use a new widget with the following Client Controller:

api.controller=function($scope, $rootScope, $timeout) {
  var handlers = [];
  var lastValues = {};

  var g_form = $scope.page.g_form;
  g_form.getFieldNames().forEach(function (fieldName) { 
		var field = g_form.getField(fieldName);
		if (field.type != 'sc_multi_row') {
			return;
		}

		var unregister = $rootScope.$on('field.change.' + fieldName, function ($event, data) {			
			// Note: data.oldValue is the *original* value (upon form load) ...
			var operation = (function (oldData, newData) {
				if (newData.length > oldData.length) {
					return 'create';
				} else if (newData.length < oldData.length) {
					return 'delete';
				} else {
					return 'update';
				}
			})(JSON.parse(lastValues[fieldName] || '[]'), JSON.parse(data.newValue || '[]'));

			// ... because of this, we simply preserve a copy of the previous value
			lastValues[fieldName] = data.newValue;

			CustomEvent.fire('scp_mrvs_changed', fieldName, operation);
		});
		
		handlers.push(unregister);
	});

	$scope.$on('$destroy', function () {
		handlers.forEach(function (fn) { fn(); });
	});
};

You also need to reference a UI Macro in the Custom Variable with the following code:

<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<script>
(function () {
	if (window.TableVariable) {
		window.TableVariable = scPlusTableVariable(window.TableVariable);
	} else {
		Object.defineProperty(window, 'TableVariable', {
			configurable: true,
			set: function (v) {
				Object.defineProperty(window, 'TableVariable', {
					configurable: true, enumerable: true, writable: true, value: scPlusTableVariable(v)
				});
			}
		});
	}

	function scPlusTableVariable(ootbTableVariable) {
		const SCPlusTableVariable = {
			notifyOperation: function (operation) {
				var res = ootbTableVariable.prototype.notifyOperation.apply(this, arguments);
				CustomEvent.fire('scp_mrvs_changed', this.internal_name, operation);
				return res;
			},

			type: 'SC+TableVariable'
		};

		return window.Class.create(ootbTableVariable, SCPlusTableVariable);
	}
})();
</script>
</j:jelly>

 

Now you can use the following onLoad - Catalog Client Script on the Catalog Item itself:
UI Type: All
Script:

function onLoad() {
	updateVariableState();
	CustomEvent.on('scp_mrvs_changed', function (mrvsName, operation) {
		if (mrvsName == 'report_name_and_email') {
			updateVariableState();
		}
	});

	function updateVariableState() {
		var mrvs = JSON.parse(g_form.getValue('report_name_and_email') || '[]');
		if (mrvs.length > 0) {
			g_form.setReadOnly('add_or_remove', true);
		} else {
			g_form.setReadOnly('add_or_remove', false);
		}
	}
}