Hide Attachment on catalog item based on the subcategory

bhanukota09
Tera Contributor

Hi All,

I have a requirement where, based on the user's selection, the URL and attachment variables should be visible and mandatory. Otherwise, the URL and attachment should be hidden.

For this, I have used:

  • A Rich Text variable type for the URL
  • An Attachment variable type for file upload

For implementing the logic, I configured an onChange Client Script.

The issue I am facing is that when I make the attachment mandatory, it does not get hidden when I select other subcategories. The attachment field remains visible, which is incorrect.

In simple terms:

  • If the subcategory is A, B, or C, the attachment should be visible and mandatory
  • If the user selects D to Z, the attachment and URL should be hidden
        var sub = g_form.getValue('subcategory');
        // alert(sub);
        g_form.setVisible('URL', false);
        g_form.setVisible('URL', false);
        g_form.setVisible('URL', false);
        g_form.setVisible('attachment', false);
        g_form.setVisible('attachment2', false);
        g_form.setVisible('attachment3', false);
        // g_form.setMandatory('attachment', false);
        // g_form.setMandatory('attachment2', false);
        // g_form.setMandatory('attachment3', false);

        //alert(sub);
        if (sub == 'A') {
            g_form.setVisible('URL', true);
            g_form.setVisible('attachment', true);
            g_form.setMandatory('attachment', true);
            // g_form.setVisible('attachment2', false);
            // g_form.setVisible('attchment3', false);
            // g_form.setMandatory('attachment2', false);
            // g_form.setMandatory('attachment3', false);
     
        } else if (sub == 'B') {
            g_form.setVisible('URL', true);
            g_form.setVisible('attachment2', true);
             g_form.setMandatory('attachment2', true);
             g_form.setVisible('attachment', false);
            g_form.setVisible('attachmen3', false);
            g_form.setMandatory('attachment', false);
            g_form.setMandatory('attachment3', false);
     
        } else if (sub == 'C') {
            g_form.setVisible('URL', true);
            g_form.setVisible('attachment3', true);
            g_form.setMandatory('attachment3', true);
            g_form.setVisible('attachment', false);
             g_form.setVisible('attachment2', false);
            g_form.setMandatory('attachment', false);
             g_form.setMandatory('attachment2', false);
        }
    }

 

1 ACCEPTED SOLUTION

Priyaranjan181
Tera Expert

Why is this not working?

 

The major issue is this line:

g_form.setMandatory('attachment', true);

combined with

g_form.setVisible('attachment', false);

for an Attachment variable.

 

Attachment variables behave differently Unlike:

Single Line Text
Reference
Choice
Checkbox

an Attachment variable is not a normal catalog variable. Internally it is rendered through a special attachment widget.
Because of that: Supported methods Some methods work: g_form.setVisible(); Sometimes.

Unsupported behavior Mandatory control is inconsistent: g_form.setMandatory(); especially when trying to hide the variable afterward.
Once marked mandatory, ServiceNow's catalog validation keeps enforcing it.

This causes: Attachment field stays visible even though the script says hide it. Exactly what you are seeing.


Problem 1: Mandatory is never reset Look carefully.

Initially: g_form.setMandatory('attachment', true); for A.

Then user changes to D.

The script does: g_form.setVisible('attachment', false);

but this is commented: // g_form.setMandatory('attachment', false);

Meaning: Attachment is still mandatory.

ServiceNow says: "I cannot hide a field that is mandatory."

Result: Field remains visible.


Problem 2: Wrong sequence Even if mandatory reset wasn't commented, sequence matters.

Incorrect sequence:

g_form.setVisible('attachment', false);
g_form.setMandatory('attachment', false);

Correct sequence:

g_form.setMandatory('attachment', false);
g_form.setVisible('attachment', false);

Always remove mandatory first. Then hide. Otherwise validation interferes.


Problem 3: Typographical mistakes I noticed several spelling mistakes.

This: g_form.setVisible('attachmen3', false); This line never executes.

should be: g_form.setVisible('attachment3', false); Missing "t".

Similarly: g_form.setVisible('attchment3', false); also incorrect.

Because of these typos: Attachment 3 may remain visible unexpectedly.


Problem 4: Duplicate code

The script has:

g_form.setVisible('URL', false);
g_form.setVisible('URL', false);
g_form.setVisible('URL', false);

three times. No reason.

Should be: g_form.setVisible('URL', false); once.

This indicates poor maintainability.


Problem 5: onChange execution If this is an onChange Catalog Client Script, it should begin with:

function onChange(control, oldValue, newValue, isLoading) {

if (isLoading)
return;

}

Otherwise: During form load, the script may execute unexpectedly and create inconsistent states.

 

Best Practice Solution

Instead of handling each attachment separately throughout the script, first reset everything.

Then enable only what's required.

 

Example:

function onChange(control, oldValue, newValue, isLoading) {

if (isLoading)
return;

var sub = g_form.getValue('subcategory');

/* Reset everything */

g_form.setVisible('URL', false);

g_form.setMandatory('attachment', false);
g_form.setMandatory('attachment2', false);
g_form.setMandatory('attachment3', false);

g_form.setVisible('attachment', false);
g_form.setVisible('attachment2', false);
g_form.setVisible('attachment3', false);


/* Apply requirement */

if (sub == 'A') {

g_form.setVisible('URL', true);

g_form.setVisible('attachment', true);
g_form.setMandatory('attachment', true);

}
else if (sub == 'B') {

g_form.setVisible('URL', true);

g_form.setVisible('attachment2', true);
g_form.setMandatory('attachment2', true);

}
else if (sub == 'C') {

g_form.setVisible('URL', true);

g_form.setVisible('attachment3', true);
g_form.setMandatory('attachment3', true);

}
}

 

If this answer helps you then please mark it Helpful.

View solution in original post

3 REPLIES 3

brianlan25
Kilo Patron

I had a similar issue. The fix was to make sure that you set mandatory to false before you try and change the visibility. Also you should use setDisplay instead of setVisible. This was based on best practices according to impact services.

Priyaranjan181
Tera Expert

Why is this not working?

 

The major issue is this line:

g_form.setMandatory('attachment', true);

combined with

g_form.setVisible('attachment', false);

for an Attachment variable.

 

Attachment variables behave differently Unlike:

Single Line Text
Reference
Choice
Checkbox

an Attachment variable is not a normal catalog variable. Internally it is rendered through a special attachment widget.
Because of that: Supported methods Some methods work: g_form.setVisible(); Sometimes.

Unsupported behavior Mandatory control is inconsistent: g_form.setMandatory(); especially when trying to hide the variable afterward.
Once marked mandatory, ServiceNow's catalog validation keeps enforcing it.

This causes: Attachment field stays visible even though the script says hide it. Exactly what you are seeing.


Problem 1: Mandatory is never reset Look carefully.

Initially: g_form.setMandatory('attachment', true); for A.

Then user changes to D.

The script does: g_form.setVisible('attachment', false);

but this is commented: // g_form.setMandatory('attachment', false);

Meaning: Attachment is still mandatory.

ServiceNow says: "I cannot hide a field that is mandatory."

Result: Field remains visible.


Problem 2: Wrong sequence Even if mandatory reset wasn't commented, sequence matters.

Incorrect sequence:

g_form.setVisible('attachment', false);
g_form.setMandatory('attachment', false);

Correct sequence:

g_form.setMandatory('attachment', false);
g_form.setVisible('attachment', false);

Always remove mandatory first. Then hide. Otherwise validation interferes.


Problem 3: Typographical mistakes I noticed several spelling mistakes.

This: g_form.setVisible('attachmen3', false); This line never executes.

should be: g_form.setVisible('attachment3', false); Missing "t".

Similarly: g_form.setVisible('attchment3', false); also incorrect.

Because of these typos: Attachment 3 may remain visible unexpectedly.


Problem 4: Duplicate code

The script has:

g_form.setVisible('URL', false);
g_form.setVisible('URL', false);
g_form.setVisible('URL', false);

three times. No reason.

Should be: g_form.setVisible('URL', false); once.

This indicates poor maintainability.


Problem 5: onChange execution If this is an onChange Catalog Client Script, it should begin with:

function onChange(control, oldValue, newValue, isLoading) {

if (isLoading)
return;

}

Otherwise: During form load, the script may execute unexpectedly and create inconsistent states.

 

Best Practice Solution

Instead of handling each attachment separately throughout the script, first reset everything.

Then enable only what's required.

 

Example:

function onChange(control, oldValue, newValue, isLoading) {

if (isLoading)
return;

var sub = g_form.getValue('subcategory');

/* Reset everything */

g_form.setVisible('URL', false);

g_form.setMandatory('attachment', false);
g_form.setMandatory('attachment2', false);
g_form.setMandatory('attachment3', false);

g_form.setVisible('attachment', false);
g_form.setVisible('attachment2', false);
g_form.setVisible('attachment3', false);


/* Apply requirement */

if (sub == 'A') {

g_form.setVisible('URL', true);

g_form.setVisible('attachment', true);
g_form.setMandatory('attachment', true);

}
else if (sub == 'B') {

g_form.setVisible('URL', true);

g_form.setVisible('attachment2', true);
g_form.setMandatory('attachment2', true);

}
else if (sub == 'C') {

g_form.setVisible('URL', true);

g_form.setVisible('attachment3', true);
g_form.setMandatory('attachment3', true);

}
}

 

If this answer helps you then please mark it Helpful.

Tanushree Maiti
Tera Patron

Hi @bhanukota09 

 

To dynamically hide, show, and enforce mandatory rules on variables based on a user's selection, you should use a Catalog UI Policy  . It is no code/low code approach recommended by Servicenow Over Client script.

 

Here are the steps:

 

Step 1: Create the Catalog UI Policy

  1. Navigate to your Catalog Item
  2. Scroll to the Catalog UI Policies related list and click New.
  3. Fill out the following fields:
    • Short description: Hide/Show and Mandate URL and Attachment.
    • Applies to: Catalog Item (check the boxes for Applies on a Catalog Item, Applies on Requested Items, and Applies on Catalog Tasks depending on where you want this rule to run).
    • Reverse if false : Checked    // so that for D to Z category selection , it will behave reversly
  4. In the When to Apply section, set your specific choice condition:
    • [Subcategory] [isOneOf] [A,B,C]

 

Step 2: Create UI Policy Actions

After saving the UI Policy, scroll down to the Catalog UI Policy Actions related list.

Click New to create a policy action for the URL variable

  • Variable name: URL variable.
  • Mandatory: True
  • Visible: True
  • Clear Value: False

Click New again to create a policy action for the Attachment variable:

  • Variable name: Select your Attachment type variable.
  • Mandatory: True
  • Visible: True
  • Clear Value: True

Click New again to create a policy action for the Attachment2 variable:

  • Variable name: Select your Attachment type variable.
  • Mandatory: True
  • Visible: True
  • Clear Value: True

Click New again to create a policy action for the Attachment3 variable:

  • Variable name: Select your Attachment type variable.
  • Mandatory: True
  • Visible: True
  • Clear Value: True
Please Accept the solution if it assisted you with your question & Mark this response as Helpful.
Regards
Tanushree Maiti
ServiceNow Technical Architect
LinkedIn: https://www.linkedin.com/in/tanushreemaiti