Setting variables read-only from a Client Script

tim2222
Tera Expert

Hi All,

We have a sc_req_item Client Script that manages access to variables for the CMS user. It manages whether fields are read-only through variable attributes - allowing us to set read-only depending on the user's role, task state etc.

I'm now trying to set up the sc_req_item on the Service Portal using the "Form Widget", which shows the fields, variable editor and the ticket conversation.

But the Client Script isn't working on Service Portal. After investigating I've determined that variables aren't being populated in the g_form object so this doesn't do anything:

g_form.setReadOnly('variables.my_var_name', true);

Only the form fields are being populated into g_form.

I've seen other posts that describe how to set all variables read-only by modifying the widget or creating Catalog Client Scripts presumably for every form.

How can we create a script that will work across all Catalog Items to apply our desired variable behaviour?

How can a Client Scripts access the variables or a Catalog Client Script access the fields? e.g. make all variables read-only when the task is closed?

1 ACCEPTED SOLUTION

tim2222
Tera Expert

I believe I have a solution for our needs, which was prompted by this post:


Re: Interact with service portal widget in catalog item



And that this callback in the Client Script for the Form widget:


$scope.$on('spModel.gForm.initialized', function(e, gFormInstance) {



Is also being called for the embedded variable editor. Provides a scriptable location that has access to both the form fields and variables.



To make use of this I've created a custom Form widget where I added a CustomEvent fire which provides both field and variable g_form objects to observers:


var g_form;


$scope.$on('spModel.gForm.initialized', function (e, gFormInstance) {


      if (gFormInstance.getTableName() == $scope.data.f.table)


              g_form = gFormInstance;


      // Trigger an event to indicate variables are ready


      if (gFormInstance.getTableName() == null) { // Is there a better test for here?


              CustomEvent.fire('soton.variable.ready', g_form, gFormInstance);


      }


});



Then in the sc_req_item Client Script I've added an observer that will apply our variable read-only policies (and as a Client Script also has access to g_scratchpad, which the variable editor doesn't):


CustomEvent.observe('soton.variable.ready', function(g_form, g_variable_form) {



I can then perform operations over both the fields and variables e.g.


if (g_form.getValue('state') == -6) {


      g_variable_form.setReadonly('comments', true);


}



Note that g_variable_form - the g_form object on the variable editor - refers to variables using their name and does not expect a "variables." prefix.




In the many dead-ends I've gone down with this I've noticed that the Form widget and its g_form knows about variables but the Service Portal g_form class seems to be missing the equivalent functionality for handling variables that exists in Platform i.e. you can call a g_form function with "variables.{variable name}" and have it work on the variable.


View solution in original post

14 REPLIES 14

Support have raised PRB1265323 to address this. A Client Script (not Catalog Client Script) is expected to be able to manipulate variables by using the "variables." prefix, which works on Platform but is not supported on Portal.

tim2222
Tera Expert

I believe I have a solution for our needs, which was prompted by this post:


Re: Interact with service portal widget in catalog item



And that this callback in the Client Script for the Form widget:


$scope.$on('spModel.gForm.initialized', function(e, gFormInstance) {



Is also being called for the embedded variable editor. Provides a scriptable location that has access to both the form fields and variables.



To make use of this I've created a custom Form widget where I added a CustomEvent fire which provides both field and variable g_form objects to observers:


var g_form;


$scope.$on('spModel.gForm.initialized', function (e, gFormInstance) {


      if (gFormInstance.getTableName() == $scope.data.f.table)


              g_form = gFormInstance;


      // Trigger an event to indicate variables are ready


      if (gFormInstance.getTableName() == null) { // Is there a better test for here?


              CustomEvent.fire('soton.variable.ready', g_form, gFormInstance);


      }


});



Then in the sc_req_item Client Script I've added an observer that will apply our variable read-only policies (and as a Client Script also has access to g_scratchpad, which the variable editor doesn't):


CustomEvent.observe('soton.variable.ready', function(g_form, g_variable_form) {



I can then perform operations over both the fields and variables e.g.


if (g_form.getValue('state') == -6) {


      g_variable_form.setReadonly('comments', true);


}



Note that g_variable_form - the g_form object on the variable editor - refers to variables using their name and does not expect a "variables." prefix.




In the many dead-ends I've gone down with this I've noticed that the Form widget and its g_form knows about variables but the Service Portal g_form class seems to be missing the equivalent functionality for handling variables that exists in Platform i.e. you can call a g_form function with "variables.{variable name}" and have it work on the variable.


Fabian10
Tera Guru

Here's my solution.

Create a Client Script (not Catalog Client Script) which runs on the Service Portal for the table sc_req_item:

function onLoad() {

	var $ = parent.$;

	function makeVariablesReadOnly() {
		var inputs = $('sp-variable-layout sp-variable-layout').find('input, textarea, select');
		for (var i=0; i<inputs.length; i++) {
			$(inputs[i]).attr('disabled', 'disabled');
		}
		setTimeout(makeVariablesReadOnly, 1000);
	}
	
	makeVariablesReadOnly();

}

 

Advantage: Customization of Widgets not needed

Disadvantage:

- Uses undocumented parent-variable and jQuery

- Runs every second

I have had to add "form-group" to the search to make it work for all fields (for me at least)

I have embedded this into an onLoad and I am using this.document.readyState. 

If the state is not complete I call this loop function again

It if is complete, I will call the function that will do the work, but I have had to add a delay as it seems to trigger a little too quick (could be the client as their internet is a little slow at times)

 

 

Thank you Fabian. Your solution worked great for me. I did make a minor tweak because I didn't want the script to run every second; I only needed it to execute at load. Sharing my very slightly tweaked version below:

function onLoad() {

	var $ = parent.$;

	function makeVariablesReadOnly() {
		var inputs = $('sp-variable-layout sp-variable-layout').find('input, textarea, select');
		for (var i=0; i<inputs.length; i++) {
			$(inputs[i]).attr('disabled', 'disabled');
		}		
	}	
	setTimeout(makeVariablesReadOnly, 1000);
}