Catalog Ui Policy- Make Child field visible and mandatory only when the Parent selected has children

VernYerem
Tera Expert

In our location table we have Buildings and Floors. Buildings are parents to Floors. Some of our buildings have no child floors.

I'd like to make a catalog UI Policy to show the field "Floor" and make it mandatory only when the field "Building" gets a referenced values that actually has floors.

"When to apply" is easy, when Building=anything. I created the script to fire when this condition is met, but I get Java errors on the form when testing.

 

function onCondition() {
var floors = new GlideRecord("cmn_location"); //Get locations
var buildingSID = g_form.getValue('scvar_building'); //Get selected bulding's sysID
floors.addEncodedQuery('parent.sys_id='+buildingSID); //Filter for items with a parent of the selected building
floors.query();

if (floors.hasNext()) { //Check to see if query resulted in any items
    g_form.setDisplay('scvar_floor', true); //Show Floor
    g_form.setMandatory('scvar_floor', true); //Make Floor Mandatory
	} 
else {	//Else if nothing has a parent of the selected building
    g_form.setDisplay('scvar_floor', false); //Hide Floor
    g_form.setMandatory('scvar_floor', false);	//Make Floor Optional
	}
}

 

I haven't done a ton of scripting on UI Policies, feels like im missing something simple. 

1 ACCEPTED SOLUTION

jcmings
Mega Sage

Since a UI Policy script runs on the client-side, it can't execute something like a GlideRecord query (since that's server-side code). If you want to run this check, you'll need to use GlideAjax and contact a script include, passing through the sys_id of the building. Your response from the script include will dictate what you do in the client script (e.g. you would change the floors.hasNext() to something like response == 'success' in your if statement).

 

If you need help getting started with GlideAjax, check out this comment I left yesterday. You'll have to shift the code a little bit, but the principle is the same.

 

I believe you'll also want to shift this all to a onChange and/or onLoad client script rather than using a UI Policy. This way, the system can adjust if the selected Building changes. 

View solution in original post

8 REPLIES 8

Not a good idea especially since it doesn't work in this case lol. Reading up on Glide Ajax now, seems pretty straight forward.

jcmings
Mega Sage

Since a UI Policy script runs on the client-side, it can't execute something like a GlideRecord query (since that's server-side code). If you want to run this check, you'll need to use GlideAjax and contact a script include, passing through the sys_id of the building. Your response from the script include will dictate what you do in the client script (e.g. you would change the floors.hasNext() to something like response == 'success' in your if statement).

 

If you need help getting started with GlideAjax, check out this comment I left yesterday. You'll have to shift the code a little bit, but the principle is the same.

 

I believe you'll also want to shift this all to a onChange and/or onLoad client script rather than using a UI Policy. This way, the system can adjust if the selected Building changes. 

This is what I worked out, seems to work alright. 

Script Include:

var DoesParentLocationHaveChildScriptInclude = Class.create();
DoesParentLocationHaveChildScriptInclude.prototype = Object.extendsObject(AbstractAjaxProcessor, {
    DoesParentLocationHaveChildFunction: function() {
        var ParentID = this.getParameter('sysparm_parent');

        var gr = new GlideRecord('cmn_location');
        gr.addEncodedQuery('parent.sys_id=' + ParentID); 
        gr.query();

        if (gr.next()) {
            return 'true'; 
        } else {
            return 'false';
        }
    }
});

 
Catalog Client Script:

function onChange(control, oldValue, newValue, isLoading) {
    if (isLoading || newValue == '') {
        return;
    }
    var buildingSID = g_form.getValue('scvar_building');
    var ga = new GlideAjax("DoesParentLocationHaveChildScriptInclude"); 
    ga.addParam("sysparm_name", 'DoesParentLocationHaveChildFunction'); 
    ga.addParam("sysparm_parent", buildingSID);
    ga.getXML(result);
}

function result(response) {
	var answer = response.responseXML.documentElement.getAttribute("answer");
    if (answer == "true") {
    g_form.setDisplay('scvar_floor', true);
    g_form.setMandatory('scvar_floor', true);
} if(answer == "false"){
	g_form.setMandatory('scvar_floor', false);
    g_form.setDisplay('scvar_floor', false);
}
}


If you see anything that can be improved upon, let me know!

Nice! Glad it works and thanks for sharing your code. The only thing I can think to change--and it's very minor--is to use newValue instead of doing the g_form.getValue (I am assuming that your onChange field is scvar_building). 

 

So you'd pass in newValue as the param instead of buildingSID (and then won't need the variable declaration at all).

ga.addParam("sysparm_parent", newValue);