diff --git a/Modern Development/Service Portal Widgets/Dynamic Table and Record Selector/Client Side.js b/Modern Development/Service Portal Widgets/Dynamic Table and Record Selector/Client Side.js new file mode 100644 index 0000000000..24828cef73 --- /dev/null +++ b/Modern Development/Service Portal Widgets/Dynamic Table and Record Selector/Client Side.js @@ -0,0 +1,94 @@ +api.controller=function($scope, $http, spUtil, $rootScope, $timeout, spModal) { + /* widget controller */ + var c = this; + + // Initialize scope variables + $scope.tablename = { + displayValue: '', + value: '', + name: 'tablename' + }; + $scope.record = { + displayValue: '', + value: '', + name: 'record' + }; + $scope.selectedTable = ''; + $scope.TableSysId = ''; + + // Handle field changes (table/record) + $scope.$on("field.change", function(evt, parms) { + if (parms.field.name === 'tablename') { + // Get sys_id of selected table → fetch actual table name & label + var sysId = parms.newValue; + var url = '/api/now/table/sys_db_object/' + sysId + '?sysparm_fields=name,label'; + $http.get(url).then(function(res) { + if (res.data.result) { + $scope.selectedTable = res.data.result.name; + $scope.selectedTableLabel = res.data.result.label; + c.getDisplayField($scope.selectedTable, sysId); // fetch display field + } + }); + } else if (parms.field.name === 'record') { + // Save selected record sys_id + $scope.TableSysId = parms.newValue; + } + }); + + // Get display field for a table (recursive if needed) + c.getDisplayField = function(tableName, tablesysId) { + var url = '/api/now/table/sys_dictionary' + + '?sysparm_query=name=' + tableName + '^display=true' + + '&sysparm_fields=element' + + '&sysparm_limit=1'; + + $http.get(url).then(function(response) { + if (response.data.result && response.data.result.length > 0) { + // Found display field + $scope.recorddisplayValue = response.data.result[0].element; + } else { + // Check parent table + var parentsysIdUrl = '/api/now/table/sys_db_object/' + tablesysId + '?sysparm_fields=super_class'; + $http.get(parentsysIdUrl).then(function(parentRes) { + var parentTable = parentRes.data.result.super_class.value; + + if (!parentTable) { + // No parent - fallback checks + var nameCheckUrl = '/api/now/table/sys_dictionary' + + '?sysparm_query=name=' + tableName + '^element=name' + + '&sysparm_fields=element&sysparm_limit=1'; + + $http.get(nameCheckUrl).then(function(nameRes) { + if (nameRes.status == 200) { + $scope.recorddisplayValue = 'name'; + } else { + var numberCheckUrl = '/api/now/table/sys_dictionary' + + '?sysparm_query=name=' + tableName + '^element=number' + + '&sysparm_fields=element&sysparm_limit=1'; + + $http.get(numberCheckUrl).then(function(numberRes) { + if (numberRes.status == 200) { + $scope.recorddisplayValue = 'number'; + } else { + $scope.recorddisplayValue = 'sys_id'; // Final fallback + } + }); + } + }); + + } else { + // Parent exists - recurse + var parentNameUrl = '/api/now/table/sys_db_object/' + parentTable + '?sysparm_fields=name'; + $http.get(parentNameUrl).then(function(parentResname) { + var parentTableName = parentResname.data.result.name; + c.getDisplayField(parentTableName, parentTable); // recursive lookup + }); + } + }); + } + }, function(error) { + spModal.alert("Error fetching display field: " + error); + }); + }; + +}; diff --git a/Modern Development/Service Portal Widgets/Dynamic Table and Record Selector/HTML.html b/Modern Development/Service Portal Widgets/Dynamic Table and Record Selector/HTML.html new file mode 100644 index 0000000000..65ec867a99 --- /dev/null +++ b/Modern Development/Service Portal Widgets/Dynamic Table and Record Selector/HTML.html @@ -0,0 +1,26 @@ +
+
+ + + +
+ + +
+ + + +
+
diff --git a/Modern Development/Service Portal Widgets/Dynamic Table and Record Selector/README.md b/Modern Development/Service Portal Widgets/Dynamic Table and Record Selector/README.md new file mode 100644 index 0000000000..7aaeb51c75 --- /dev/null +++ b/Modern Development/Service Portal Widgets/Dynamic Table and Record Selector/README.md @@ -0,0 +1,78 @@ +Widget Name: Dynamic Table and Record Selector + +Overview: +This ServiceNow Service Portal widget allows users to dynamically select any table and then choose a record from that table. The widget automatically determines which field should be shown as the display field for the selected table. It also handles parent table inheritance and provides fallback options for display fields. + +Main Features: + +Lists all tables from the sys_db_object table. + +Automatically finds the correct display field (field with display=true). + +Supports parent table lookup if the child table does not have a display field. + +Provides fallback checks for fields named "name", "number", or defaults to "sys_id". + +Uses ServiceNow REST APIs to fetch metadata and record data dynamically. + +Works with the standard sn-record-picker directive in Service Portal. + +How It Works: + +The first record picker displays all tables from sys_db_object using the label field. + +When the user selects a table, the widget fetches the actual table name and label using the sys_id. + +The controller calls the getDisplayField function to determine which field should be displayed in the record picker. + +It checks sys_dictionary for a field with display=true. + +If found, that field is used as the display field. + +If not found, it checks if the table has a parent (super_class). + +If a parent exists, it recursively checks the parent table. + +If there is no parent, it uses fallback checks for "name", then "number", and finally "sys_id". + +The second record picker then displays the records from the selected table using the determined display field. + +When the user selects a record, its sys_id is stored in the variable TableSysId. + +Example Flow: + +Select “Incident” from the table picker. + +The widget detects that the display field is “number”. + +The record picker lists incident numbers. + +When a record is selected, its sys_id is saved for further use. + +Technologies Used: + +ServiceNow Service Portal + +AngularJS (spUtil, spModal) + +ServiceNow REST API: + +/api/now/table/sys_db_object + +/api/now/table/sys_dictionary + +Use Cases: + +Creating dynamic reference selectors for any table. + +Building tools that link or map data between tables. + +CMDB record selection where tables may have inheritance. + +Generic admin utilities or catalog forms needing flexible input. + +File Components: + +HTML Template: Contains two sn-record-picker elements for selecting table and record. + +Client Controller (JS): Handles field change events, fetches table metadata, determines display fields, and manages recursion logic.