Skip to content

Commit 56600c8

Browse files
authored
Merge branch 'ServiceNowDevProgram:main' into Check-Attchment
2 parents 611dc63 + fe3b963 commit 56600c8

File tree

36 files changed

+1175
-90
lines changed

36 files changed

+1175
-90
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
function onSubmit() {
2+
//Type appropriate comment here, and begin script below
3+
var description = g_form.getValue('description');
4+
var state = g_form.getValue('state');
5+
6+
if ((!description) && (state == 'completed')) {
7+
g_form.addErrorMessage('Please provide Description Value, Description Cannot be empty');
8+
9+
return false;
10+
}
11+
12+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
When an Incident record is being closed, the system should validate that the Description field is not empty and state is completed.
2+
If the Description field is blank and state is completed, the record submission (update) should be aborted, and the user should be prompted to provide a description before closing the incident.
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Form Dirty State Prevention
2+
3+
## Overview
4+
Detects form changes and warns users before navigating away or closing the form, preventing accidental data loss.
5+
6+
## What It Does
7+
- Tracks form field changes (dirty state)
8+
- Warns user before leaving unsaved form
9+
- Allows user to cancel navigation
10+
- Works with all form fields
11+
- Prevents accidental data loss
12+
- Clean, reusable pattern
13+
14+
## Use Cases
15+
- Complex multi-field forms
16+
- Long data entry forms
17+
- Forms with expensive operations
18+
- Critical data entry (financial, medical)
19+
- Any form where accidental exit would cause issues
20+
21+
## Files
22+
- `form_dirty_state_manager.js` - Client Script to manage form state
23+
24+
## How to Use
25+
26+
### Step 1: Create Client Script
27+
1. Go to **System Definition > Scripts** (any table)
28+
2. Create new Client Script
29+
3. Set **Type** to "onChange"
30+
4. Copy code from `form_dirty_state_manager.js`
31+
5. Set to run on any field
32+
33+
### Step 2: Add Navigation Handler
34+
1. Add to form's onLoad script:
35+
```javascript
36+
// Initialize dirty state tracking
37+
var formStateManager = new FormDirtyStateManager();
38+
```
39+
40+
### Step 3: Test
41+
1. Open form and make changes
42+
2. Try to navigate away without saving
43+
3. User sees warning dialog
44+
4. User can choose to stay or leave
45+
46+
## Example Usage
47+
```javascript
48+
// Automatically tracks all field changes
49+
// When user tries to close/navigate:
50+
// "You have unsaved changes. Do you want to leave?"
51+
// - Leave (discard changes)
52+
// - Stay (return to form)
53+
```
54+
55+
## Key Features
56+
- ✅ Detects any field change
57+
- ✅ Persistent across form interactions
58+
- ✅ Works with new records and updates
59+
- ✅ Ignores read-only fields
60+
- ✅ Resets after save
61+
- ✅ No performance impact
62+
63+
## Output Examples
64+
```
65+
User opens form and changes a field
66+
→ Form marked as "dirty"
67+
68+
User clicks close/back button
69+
→ Warning dialog appears: "You have unsaved changes"
70+
71+
User clicks Leave
72+
→ Form closes, changes discarded
73+
74+
User clicks Save then navigates
75+
→ No warning (form is clean)
76+
```
77+
78+
## Customization
79+
```javascript
80+
// Customize warning message
81+
var warningMessage = "Warning: You have unsaved changes!";
82+
83+
// Add specific field tracking
84+
g_form.addOnFieldChange('priority', myCustomHandler);
85+
86+
// Reset dirty flag after save
87+
g_form.save(); // Automatically triggers cleanup
88+
```
89+
90+
## Requirements
91+
- ServiceNow instance
92+
- Client Script access
93+
- Any table form
94+
95+
## Browser Support
96+
- Chrome, Firefox, Safari, Edge (all modern browsers)
97+
- Works with ServiceNow classic and modern UI
98+
99+
## Related APIs
100+
- [g_form API](https://docs.servicenow.com/bundle/sandiego-application-development/page/app-store/dev_apps/concept/c_FormAPI.html)
101+
- [Client Script Events](https://docs.servicenow.com/bundle/sandiego-application-development/page/app-store/dev_apps/concept/c_ClientScriptEvents.html)
102+
- [Form Field Changes](https://docs.servicenow.com/bundle/sandiego-application-development/page/app-store/dev_apps/concept/c_FieldChanges.html)
103+
104+
## Best Practices
105+
- Apply to important data entry forms
106+
- Test with real users
107+
- Consider accessibility for screen readers
108+
- Use with save shortcuts (Ctrl+S)
109+
- Combine with auto-save patterns
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Client Script: Form Dirty State Manager
2+
// Purpose: Track form changes and warn user before leaving with unsaved changes
3+
4+
var FormDirtyStateManager = Class.create();
5+
FormDirtyStateManager.prototype = {
6+
initialize: function() {
7+
this.isDirty = false;
8+
this.setupFieldChangeListeners();
9+
this.setupNavigationWarning();
10+
},
11+
12+
// Mark form as changed when any field is modified
13+
setupFieldChangeListeners: function() {
14+
var self = this;
15+
g_form.addOnFieldChange('*', function(control, oldValue, newValue, isLoading) {
16+
// Ignore system updates and form loads
17+
if (isLoading || oldValue === newValue) {
18+
return;
19+
}
20+
self.setDirty(true);
21+
});
22+
},
23+
24+
// Warn user before navigating away with unsaved changes
25+
setupNavigationWarning: function() {
26+
var self = this;
27+
28+
// Warn on form close attempt
29+
window.addEventListener('beforeunload', function(e) {
30+
if (self.isDirty && !g_form.isNewRecord()) {
31+
e.preventDefault();
32+
e.returnValue = 'You have unsaved changes. Do you want to leave?';
33+
return e.returnValue;
34+
}
35+
});
36+
37+
// Warn on GlideForm navigation
38+
g_form.addOnSave(function() {
39+
// Reset dirty flag after successful save
40+
self.setDirty(false);
41+
return true;
42+
});
43+
},
44+
45+
setDirty: function(isDirty) {
46+
this.isDirty = isDirty;
47+
if (isDirty) {
48+
// Optional: Show visual indicator
49+
document.title = '* ' + document.title.replace(/^\* /, '');
50+
gs.info('[Form State] Unsaved changes detected');
51+
}
52+
},
53+
54+
isDirtyState: function() {
55+
return this.isDirty;
56+
}
57+
};
58+
59+
// Initialize on form load
60+
var formDirtyState = new FormDirtyStateManager();
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
>**UI Action**
2+
When a new Incident record is created, user can come to incident ticket and assigned to themself. Once they click on UI Action.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
var currentUser = gs.getUserID(); //Getting loggedIn User Id
2+
3+
//Checing wheather user is available or not in Assignee field
4+
if(current.assigned_to == ""){ //checking assigned to is there or not
5+
current.assigned_to = currentUser; //Setting the current loggedIn user
6+
current.update(); //updating the record.
7+
gs.addInfoMessage("Incident has been assigned to You.");
8+
action.setRedirectURL(current);
9+
} else {
10+
gs.addErrorMessage("Incident is already assigned");
11+
action.setRedirectURL(current);
12+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# 🧩 ServiceNow Asset QR Code Generator (UI Action)
2+
3+
This repository contains a **ServiceNow UI Action** script that generates and displays a QR Code for an Asset record from list view.
4+
When the user selects a record and clicks the UI Action, a modal window pops up showing a dynamically generated QR Code that links to asset details.
5+
6+
7+
A supporting **Script Include** (server-side) is required in your ServiceNow instance but **is not included** in this repository.
8+
At the bottom of file , a sample Script Include Code is given , check for the reference.
9+
10+
---
11+
12+
## 🚀 Features
13+
14+
- Generates a QR Code for the selected Asset record.
15+
- Displays the QR Code inside a ServiceNow modal (`GlideModal`).
16+
- Uses **QrIckit API** for quick and free QR code generation.
17+
- Clean, modular client-side code that integrates seamlessly with UI Actions.
18+
- Includes a `qr-code-image` file showing example QR Code generated.
19+
20+
---
21+
22+
## 🧠 How It Works
23+
24+
1. The `onClickQR()` function is triggered when the user clicks a UI Action button.
25+
2. It calls `generateQRCodeForAsset(sys_id)` and passes the record’s `sys_id`.
26+
3. A `GlideAjax` request fetches asset data from a **Script Include** on the server.
27+
4. That data is encoded and sent to the **QrIckit** API to generate a QR Code image.
28+
5. A ServiceNow modal (`GlideModal`) displays the generated QR Code to the user.
29+
30+
---
31+
32+
33+
**Note :**
34+
1) As the UI action calls a Script Include , in this folder no script include is present
35+
2) You can modify script include part as required(i.e Which fields are to be shown when QR is scanned)
36+
3) A sample Client Callable Script-Include is given here.
37+
38+
``` Script Include Code
39+
var GenerateAssetQR = Class.create();
40+
GenerateAssetQR.prototype = Object.extendsObject(AbstractAjaxProcessor, {
41+
getAssetQRData: function() {
42+
var sys_id = this.getParameter('sysparm_sys_id');
43+
var asset = new GlideRecord('alm_asset');
44+
if (asset.get(sys_id)) {
45+
return 'Asset: ' + asset.name + ', Serial: ' + asset.serial_number;
46+
}
47+
return 'Invalid asset record.';
48+
}
49+
});
50+
```
87.7 KB
Loading
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
function onClickQR() {
2+
generateQRCodeForAsset(g_sysId);//get the sysid of selected record
3+
}
4+
5+
function generateQRCodeForAsset(sys_id) {
6+
var ga = new GlideAjax('GenerateAssetQR');//Script Include which stores data to be presented when QR-Code is Scanned
7+
ga.addParam('sysparm_name', 'getAssetQRData');
8+
ga.addParam('sysparm_sys_id', sys_id);
9+
10+
ga.getXMLAnswer(function(response) {
11+
var qrData = response;
12+
var qrURL = 'https://qrickit.com/api/qr.php?d=' + encodeURIComponent(qrData) + '&addtext=Get Asset Data';
13+
//QrIckit is a tool using which Customized QR-Codes can be generated
14+
var modalHTML = `
15+
<div style="text-align:center">
16+
<img id="qrCodeImage" src="${qrURL}" alt="QR Code" style="margin-bottom:10px;" />
17+
<p>Scan to view asset details</p>
18+
</div>
19+
`;
20+
21+
var gModal = new GlideModal("QR Code");
22+
gModal.setTitle('Asset QR Code');
23+
gModal.setWidth(500);
24+
gModal.renderWithContent(modalHTML);
25+
});
26+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
**Calculate the due date based on the Priority**
2+
3+
Script Type: UI Action, Table: incident, Form button: True, Show update: True, Condition: (current.due_date == '' && current.priority != '5'), OnClick: functionName()
4+
5+
Script Type: Script Include, Glide AJAX enabled: False
6+
7+
Schedule- Name: Holidays, Time Zone: GMT
8+
9+
Schedule Entry - Name: New Year's Day, Type: Exclude, Show as: Busy, When: 31-12-2024, To: 01-01-2025
10+
Schedule Entry - Name: Christmas Day, Type: Exclude, Show as: Busy, When: 24-12-2025, To: 25-12-2025
11+
Schedule Entry - Name: Thanksgiving Day, Type: Exclude, Show as: Busy, When: 26-11-2025, To: 27-11-2025
12+
Schedule Entry - Name: Diwali, Type: Exclude, Show as: Busy, When: 19-10-2025, To: 20-10-2025
13+
14+
**Goal:** To Calculate Due-Date based on Priority with some conditions.
15+
16+
**Walk through of code:** So in this use case the UI Action is been used and then Script Include for server calculate is used.So the main to calculate the due-date by the user trigger.
17+
18+
UI Action- So this button will check the priority and check the due date field is empty or not if not then will fetch the value of "Priority" and "Created date" and pass the data to the Script Include for calculation once it gets the response will populate the value to the due_date field in the incident table and then update it.
19+
20+
Script Include- The role of this is to get the "Priority" and "Created date" based on prioriy this will calculate the time and date by using th GlidDateTime API and the will do some additional changes based on each priorit which is mentioned below and then return the response back to the UI Action,
21+
22+
Schedule & Schedule Entry- It is used for the P3 and P4 Priority which is mentioned below for the use case.To exclude the Holidays.
23+
24+
These are the use case which the above functionality works,
25+
26+
**1-> P1** - add 4hrs to the Created date
27+
**2-> P2 **- add 4hrs to the Created date but if it's exceed the working hrs of of 5 PM the add to the next day or if the is before the working hours of 8 AM set 5 PM to the same Created date.
28+
**3-> P3 or P4** - Kind of low priority so add the due date to the next day but it should exclude the holidays and the weekend's and the populate the next business working day.
29+
**4-> P5 **- User manually will populate the due date based on the process.
30+
31+
The UI Action on the Incident Form
32+
<img width="815" height="382" alt="Button" src="https://github.com/user-attachments/assets/68876b10-e6e0-43b9-9ecf-f6eb95b7ef87" />
33+
34+
UI Action which will call the Script Include
35+
<img width="556" height="425" alt="UI Action" src="https://github.com/user-attachments/assets/2715232a-000b-4520-8b1a-f5bf72afdaa9" />
36+
37+
Script Include
38+
<img width="817" height="416" alt="SI" src="https://github.com/user-attachments/assets/5ddb332c-d23f-4746-b014-1a71acb59186" />
39+
40+
Schedules and Schedule Entry
41+
<img width="839" height="431" alt="Schedules" src="https://github.com/user-attachments/assets/f96ea4dc-e2d4-4d8f-87b7-67df66a2d8af" />
42+
<img width="917" height="370" alt="Schedule Entry" src="https://github.com/user-attachments/assets/c4fec5ce-8ee4-46cc-8673-2d22a27290f1" />
43+
44+
Output
45+
<img width="828" height="356" alt="Priority 1" src="https://github.com/user-attachments/assets/7f4049b6-294e-4064-bab1-e2d1ab938bfd" />
46+
<img width="817" height="416" alt="Priority 2" src="https://github.com/user-attachments/assets/37f0cffd-f05c-4f4d-bf35-36090f02ee3b" />
47+
<img width="815" height="334" alt="Priority 4" src="https://github.com/user-attachments/assets/0ab4ab27-4726-4ea7-b99e-7e35f9b0f4c7" />

0 commit comments

Comments
 (0)