State flow & reloading the form if state flow does not finish.

pacsum
Giga Contributor

Hi All,

I am using state flows in Eureka and have come across this situation which I am not sure how to rectify.

Here is the scenario:

Starting state is : Work in progress

Ending state: Pending

In my state flow for this I have set "Additional comments" as mandatory using the "field controls" as I want the resolver to add comment as to why it is moving to a pending state.

If the resolver hits the "Pending" Button without adding a comment, I get the system message stating the mandatory field is not filled in and that it is an invalid update, but the form shows the state as being "pending".   and hence the corresponding buttons associated for the "pending state". I   then reload the form it will revert back to the work in progress state as that is what the record is because the previous transition did not complete.

How do I go about getting the form to be reloaded, with the correct data?

Is it ok to make changes to system generated client script, that the state flows produce or is there something I am missing?

regards peter

4 REPLIES 4

davidglover
Giga Expert

Peter,



I'm having a similar issue in Helsinki, did you ever find a solution?



Thanks,


David


Hi David,



This is how I solved it,


I modified the UI action that was created for the state flow transition, by checking the "Client" and then completing my form validation one the client side, below is code example where I required a comment when resolving.



UI Action setup:


<Action name> = finresolve


<Onclick> = onclickResolve()



function onclickResolve() {


  g_form.clearMessages();



  var comments = g_form.getValue('comments');


  if (comments == '') {


  g_form.addErrorMessage('"Additional comments (Customer visible)" are mandatory when Resolving a request.');


  return false;


  }


  gsftSubmit(null, g_form.getFormElement(), 'finresolve');


}



//Code that runs without 'onclick' server-side function with no browser errors


if(typeof window == 'undefined')


  serverResolve();



function serverResolve() {


    new StateFlow().processFlow(current, 'c2acc3fe44291240aeaa8917a0e7b7f2', 'manual');


}



I hope this helps.


regards


peter


Thanks Peter.   I implemented something similar based on a ServiceNOW Guru article and it works well.



Client & Server Code in One UI Action - ServiceNow Guru



David


Aivaras Gon_aro
Tera Contributor

Hi Peter,

Far far away in the future, issue is still relevant.

Faced the exact same issue while dealing with state flows.

Went through OOTB state flows code and realized mandatory field validation does not set state to previous when validation fails. Although it looks like natural thing to do. 

If anyone still interested, how to resolve this issue, make this little tweak in StateFlow.validateMandatory

One extra check before returning the value.

validateMandatory: function(current, previous, tableName) {
		var returnValue = true;
		var table = new GlideRecord(tableName);
		var defaultValue = table.getElement('state').getED().getDefault();
		if (defaultValue.indexOf('javascript:') == 0) {
			table.putCurrent();
			defaultValue = GlideEvaluator.evaluateString(defaultValue);
			table.popCurrent();
		}
		
		var gr = new GlideRecord("sf_state_flow");
		gr.addQuery("table", tableName);
		gr.addQuery("mandatory_fields", "!=", "");
		gr.addQuery("end_text", current.state);
		var cond = gr.addQuery("start_text", "");
		
		if (!current.isNewRecord())
			cond.addOrCondition("start_text", previous.state);
		else
			cond.addOrCondition("start_text", defaultValue);
		
		gr.addQuery("active", "true");
		gr.query();
		while (gr.next()) {
			var mandatoryFields = this._translateFields(gr.mandatory_fields);
			if (!mandatoryFields)
				continue;
			var mandatoryList = mandatoryFields.split(",");
			for (var i=0; i < mandatoryList.length; i++) {
				// if empty, fail
				if (mandatoryList[i]) {
					if (!current.getValue(mandatoryList[i])) {
						gs.addErrorMessage(gs.getMessage('Mandatory field not filled in for {0}', this._getDisplay(mandatoryList[i], tableName, current)));
						returnValue = false;
					}
				}
			}
		}
		// set state back to previous, validation have not passed
		if(!returnValue) current.state = previous.state; //new line!
		
		return returnValue;
	}

 

Hope that helps,

Aivaras