The Zurich release has arrived! Interested in new features and functionalities? Click here for more

adding attachments from a cloned form widget in a scoped application

Suvitha Murugan
Tera Contributor

Hi Everyone,
I am facing issues displaying attachments in a cloned Form widget within a scoped application. Your guidance and support on this would be greatly appreciated. Thanks in advance.

HTML:

<div ng-if="::!data.isValid && !data.emptyStateTemplate" class="panel panel-default">
<div class="panel-body wrapper-lg text-center">
<span ng-if="!data.tableUnsupported">${Record not found}</span>
<span ng-if="data.tableUnsupported">${Form view not supported for requested table}</span>
</div>
</div>

<div ng-if="!data.isValid && data.emptyStateTemplate" class="panel-shift">
<div class="empty-state-wrapper panel panel-default" ng-include="data.emptyStateTemplate"></div>
</div>

<div ng-if="data.isValid" class="panel-shift">
<div class="" ng-if="!data.f._view.length && data.hideRelatedLists && data.emptyStateTemplate">
<div class="empty-state-wrapper panel panel-default" ng-include="data.emptyStateTemplate"></div>
</div>

<div class="" ng-if="!data.f._view.length && data.hideRelatedLists && !data.emptyStateTemplate">
<div class="panel panel-default">
<div class="panel-heading"><span class="panel-title">{{data.f.title}}</span> <span ng-if="::options.showFormView == 'true' && data.f.view != ''">[{{data.f.view_title}} view]</span></div>
<div class="panel-body wrapper-lg text-center">
${No elements to display}
</div>
</div>
</div>

<!-- readOnly due to scope -->
<div ng-if="isPageReady && data.f.outOfScope" class="read-only-message">
<div class="alert alert-info sp-cross-scope" role="alert">
<p>${This record is in the <strong>{{data.f.recordScopeLabel}}</strong> application, but <strong>{{data.f.currentScopeLabel}}</strong> is the current application.}</p>
</div>
</div>
<div ng-show="isPageReady" class="panel panel-default" ng-if="data.f._view.length || !data.hideRelatedLists" >
<div class="panel-heading" ng-if="data.f.title.length" sp-context-menu="getUIActionContextMenu(event)">
<span class="dropdown m-r-xs" ng-if="(data.isAdmin || getUIActions('context').length > 0) && options.omitHeaderOptions != 'true'">
<button aria-label="${{{data.f.label}} Form menu}" title="${{{data.f.label}} Form menu}" class="btn btn-form-menu dropdown-toggle glyphicon glyphicon-menu-hamburger" style="line-height: 1.4em" id="adminMenu" data-toggle="dropdown" data-placement="bottom" aria-haspopup="true" aria-expanded="false" autofocus="true"></button>
<ul class="dropdown-menu" aria-labelledby="adminMenu">
<li ng-if="::data.isAdmin"><a ng-href="/{{data.f.table}}.do?sys_id={{data.f.sys_id}}&sysparm_view={{data.f.view}}" target="_blank" tabindex="-1">${Open in platform}</a></li>
<li ng-if="::data.isAdmin" class="dropdown-header" tabindex="-1">${Configure}</li>
<li ng-if="::data.isAdmin"><a href="/slushbucket.do?sysparm_referring_url={{adminMenu.encodedPageUrl}}&sysparm_list={{data.f._sections[0].id}}&sysparm_form=section&sysparm_view={{data.f.view}}" target="_blank" tabindex="-1">${Form Layout}</a></li>
<li ng-if="::data.isAdmin"><a href="/slushbucket.do?sysparm_referring_url={{adminMenu.encodedPageUrl}}&sysparm_list={{data.f.table}}&sysparm_form=related_list&sysparm_view={{data.f.view}}" target="_blank" tabindex="-1">${Related Lists}</a></li>
<li ng-if="::data.isAdmin"><a href="?id=lf&table=sys_ui_policy&filter=table%3D{{data.f.table}}%5EORtableIN{{data.tableHierarchy}}%5Eactive%3Dtrue%5Eui_type%3D1%5EORui_type%3D10" ng-click="openRelatedList($event, {id:'lf', table: 'sys_ui_policy', filter: 'table%3D{{data.f.table}}%5EORtableIN{{data.f.table}},sys_metadata%5Eactive%3Dtrue%5Eui_type%3D1%5EORui_type%3D10'})" tabindex="-1">${UI Policies} <span class="badge pull-right" ng-if="f.policy.length">{{f.policy.length}}</span></a></li>
<li ng-if="::data.isAdmin"><a href="?id=lf&table=sys_script_client&filter=table%3D{{data.f.table}}%5EORtableIN{{data.tableHierarchy}}%5Eactive%3Dtrue%5Eui_type%3D1%5EORui_type%3D10" ng-click="openRelatedList($event, {id: 'lf', table: 'sys_script_client', filter: 'table%3D{{data.f.table}}%5EORtableIN{{data.f.table}},sys_metadata%5Eactive%3Dtrue%5Eui_type%3D1%5EORui_type%3D10'})" tabindex="-1">${Client Scripts} <span class="badge pull-right" ng-if="adminMenu.getClientScriptCount()">{{adminMenu.getClientScriptCount()}}</span></a></li>
<li ng-if="getUIActions('context').length > 0 && data.isAdmin" role="separator" class="divider"></li>
<li ng-repeat="action in getUIActions('context')"><a href="" ng-click="triggerUIAction(action)" tabindex="-1">{{action.name}}</a></li>
<li ng-if="::data.isAdmin || getUIActions('context').length > 0" role="separator" class="divider"></li>
<li><a target="_new" href="/{{data.f.table}}.do?PDF&sys_id={{data.sys_id}}&sysparm_view={{data.f.view}}" tabindex="-1">${Export to PDF}</a></li>
<li><a target="_new" href="/{{data.f.table}}.do?PDF&landscape=true&sys_id={{data.sys_id}}&sysparm_view={{data.f.view}}" tabindex="-1">${Export to PDF (landscape)}</a></li>
</ul>
</span>

<!-- optional "Open in platform" link when omitHeaderOptions is true -->
<span class="dropdown m-r-xs" ng-if="::data.isAdmin && options.omitHeaderOptions == 'true' && options.ensurePlatformLink == 'true'">
<button aria-label="${{{data.f.label}} Form menu}" title="${{{data.f.label}} Form menu}" class="btn btn-form-menu dropdown-toggle glyphicon glyphicon-menu-hamburger" style="line-height: 1.4em" id="platformLink" data-toggle="dropdown" data-placement="botton" aria-haspopup="true" aria-expanded="false"></button>
<ul class="dropdown-menu" aria-labelledby="platformLink">
<li><a ng-href="/{{data.f.table}}.do?sys_id={{data.f.sys_id}}&sysparm_view={{data.f.view}}" target="_blank" tabindex="-1">${Open in platform}</a></li>
</ul>
</span>

<span class="panel-title" role="heading" aria-level="{{embeddedInModal ? '1' : '2'}}">{{data.f.title}}</span> <span ng-if="::options.showFormView == 'true' && data.f.view != ''">[{{data.f.view_title}} view]</span>
<div ng-if="::attachmentHandler && data.canAttach" title="{{::data.addAttachmentMsg}}" class="pull-right attachment-button">
<sp-attachment-button modal="true" supported-extensions="{{::data.supportedAttachmentExtensions}}"></sp-attachment-button>
</div>
<div ng-if="embeddedInModal && isCloseButtonDisplayed">
<i class="fa fa-close text-base sp-form-modal-close-button" ng-click="cancel()" role="button" aria-label="{{data.closeWindowMsg}}" tabindex="0" data-original-title="{{data.closeWindowMsg}}" data-toggle="tooltip" data-placement="bottom"></i>
</div>
</div>
<div class="panel-body">
<!-- performance debug -->
<div ng-if="data.show_sql">
<div class="comment">
<span ng-if="data.f._perf.sql_count">${SQL Statements {{data.f._perf.sql_count}}}, </span>
<span>${Time {{data.f._perf.time}}}</span>
</div>
<div ng-repeat="s in data.f._perf.sql" class="{{s.type}}">
{{s.statement}}
</div>
</div>
<!-- attachments -->
<sp-attachment-manager table="::data.table" sys-id="data.f._attachmentGUID" omit-edit="::!data.canAttach"></sp-attachment-manager>
<!-- asterisk info text -->
<div ng-if="mandatory.length > 0" class="asterisk-div">
<span class="fa fa-asterisk asterisk mandatory" title="${asterisk}"></span> ${Indicates required}
</div>
<!-- form -->
<form id="widget-form">
<div>
<sp-model form_model="data.f" mandatory="mandatory" embedded_in_modal="embeddedInModal"></sp-model>
</div>
</form>
<!-- UI Action Links -->
<!-- <div ng-if="getUIActions('link').length > 0">
<label class="h4" role="heading" aria-level="{{embeddedInModal ? '2' : '3'}}" style="margin: 0;">${Related Links}</label>
<nav aria-label="${Related Links}">
<div ng-repeat="action in getUIActions('link')">
<a href ng-click="triggerUIAction(action)" gsft_id="{{::action.sys_id}}">{{::action.name}}</a>
</div>
</nav>
</div>-->
<!-- related lists -->
<div>
<sp-widget widget="data.editChangeReqDataTableWidget"></sp-widget>
</div>
</div>

<!-- <div class="panel-footer">
<!-- Rework Button -->
<div style="display: flex; gap: 10px;">
<sp-widget widget="data.rework"></sp-widget>
<sp-widget widget="data.withdraw"></sp-widget>
<sp-widget widget="data.cancel"></sp-widget>
</div>
</div>
</div>


Client Script:

function($rootScope, $scope, $timeout, $location, $log, $window, spUtil, nowAttachmentHandler, spAriaUtil, spNavStateManager) {
var c =this;  

 $scope.submitting = false;
  $scope.mandatory = [];
  $scope.errorMessages = [];
  $scope.data.show_sql = false;
  $scope.saveButtonSuffix = spUtil.getAccelerator('s');
  $scope.isPageReady = false;
  $scope.embeddedInModal = false;
  $scope.adminMenu = {
    encodedPageUrl: encodeURIComponent($location.url()),
    getClientScriptCount: function() {
      var count = 0;
      if ($scope.data.f.client_script) {
        count += $scope.data.f.client_script.onChange.length;
        count += $scope.data.f.client_script.onLoad.length;
        count += $scope.data.f.client_script.onSubmit.length;
      }
      return count;
    }
  };
    var tableId = $scope.data.sys_id != -1 ? $scope.data.sys_id : ($scope.data.f ? $scope.data.f._attachmentGUID : -1);
  if ($scope.data.table === 'sys_attachment' && tableId && tableId !== -1) {
    // redirect to platform attachment download link
      var queryParams = new URLSearchParams(location.search);
      queryParams.delete("id");queryParams.delete("table"); //removing id,table attributes in platform -> portal URL conversion.
      var queryString = (new URLSearchParams(queryParams)).toString();
      var downloadLink = window.location.origin + '/sys_attachment.do?' + queryString;
      window.location.replace(downloadLink);return;
    }
    spUtil.recordWatch($scope, "sys_attachment", "table_sys_id=" + tableId, function (response, data) {
    $scope.attachmentHandler.getAttachmentList();
    if (response.data) {
        var options = {};
        options.operation = response.data.operation;
        options.filename = response.data.display_value;
        options.sys_id = tableId;
        options.table = $scope.data.table;
        options.state = (response.data.record && response.data.record.state) ? response.data.record.state.value : "";
        if (options.operation === 'update' && options.state === 'not_available')
         $rootScope.$broadcast("attachment.updated", options);
    }
});

  $rootScope.$on('$sp.html.editor.progress', function(e, conf) {
      $scope.submitting = conf.state;
  });

  $rootScope.$on('sp.display.close.button', function(){
    $scope.isCloseButtonDisplayed = true;
  });

  $scope.getButtonClass = function(action) {
        if (action.form_style == "destructive")
            return "btn-danger";

        if (action.form_style == "primary")
            return "btn-primary";

        return "btn-default";
    };

  $scope.getUIActions = function(type) {
    if ($scope.data.disableUIActions)
      return [];
    if (type) {
      return $scope.data.f._ui_actions.filter(function(action) {
        //We handle the primary action button separately.
        return !action.primary && action['is_' + type];
      });
    } else {
      return $scope.data.f._ui_actions;
    }
  }

  $scope.getPrimaryAction = function() {
    var primaryActions = $scope.data.f._ui_actions.filter(function(action) {
      return action.primary;
    });
    return (primaryActions.length) ? primaryActions[0] : null;
  }

  $scope.getUIActionContextMenu = function(event) {
    var menu = [];
    if (event.ctrlKey)
      return menu;

    var contextActions = $scope.getUIActions('context');
    contextActions.forEach(function(action) {
      menu.push([action.name, function() {
        $scope.triggerUIAction(action);
      }]);
    });

    if (contextActions.length > 0)
      menu.push(null);
    menu.push([$scope.data.exportPDFMsg, function() {
      exportPDF("");
    }]);
    menu.push([$scope.data.exportPDFLandMsg, function() {
      exportPDF('true');
    }]);

    return menu;
  }

  function exportPDF(landscape) {
    $window.open("/" + $scope.data.f.table + ".do?PDF&landscape=" + landscape + "&sys_id=" + $scope.data.sys_id + "&sysparm_view=" + $scope.data.f.view);
  }

  //trigger the primary UI Action on save (if there is one)
  var deregister = $scope.$on('$sp.save', function() {
    var primaryAction = $scope.getPrimaryAction();
    if (primaryAction)
      $scope.delayTriggerUIAction(primaryAction);
  });
  $scope.$on('$destroy', function() {
    deregister()
  });

  $scope.$on('esLatestValueChanged', function(event, newValue) {
      $scope.data.esLatestVersion = newValue;
  });  

  $scope.triggerUIAction = function(action) {
    if ($scope.data.disableUIActions && !action.primary) {
      return;
    }

    var activeElement = document.activeElement;
    if (activeElement) {
      activeElement.blur();
    }
    $scope.$evalAsync(function() {
      if (g_form) {
        g_form.useEsLatest = function() {
            return $scope.data.esLatestVersion;
        }
        if (!g_form.submit(action.action_name || action.sys_id))
          $scope.submitting = false;
      }
    });
  }
  $scope.delayTriggerUIAction = _.debounce($scope.triggerUIAction, 1000, {
    'leading': true,
    'trailing': false
  });

        $rootScope.$on("rework", function(evt, parm){
c.data.editChangeReqDataTableWidget.data.selectedRows();
        // call server side c.server.get(). update sc_item_option record from editChangeReqDataTableWidget widget
        // call gform.submit
    });
  $scope.$on("spModel.uiActionComplete", function(evt, response, savedFormSysId) {
    if (!response.isInsert &&  ($scope.data.sys_id !== savedFormSysId))
      return;

    $scope.submitting = false;
    if (response.isActionAborted)
      return;

    var sysID = (response.isInsert) ? response.sys_id : $scope.data.sys_id;
        $scope.data.isInsert = response.isInsert;

    if (response.isInsert && !$scope.data.preventUrlUpdateOnSubmit) {
        var search = $location.search();
        search.sys_id = sysID;
        search.spa = 1;
        $location.search(search).replace();
    }

    loadForm($scope.data.table, sysID).then(constructResponseHandler(response));
  });

  function constructResponseHandler(response) {
    return function() {
      $rootScope.$broadcast("sp.form.submitted", {sys_id: (response.isInsert) ? response.sys_id : $scope.data.sys_id});
      var message;
      var eventName = "sp.form.record.updated";
      if (response.isInsert) {
        message = $scope.data.recordAddedMsg;
      } else
        message = $scope.data.updatedMsg;

      $scope.data.hideRelatedLists = hideRelatedLists();
      $scope.$emit(eventName, $scope.data.f._fields, $scope.data.sys_id);
      $rootScope.$broadcast(eventName, $scope.data.f._fields, $scope.data.sys_id);
      $scope.status = message;
      spUtil.addTrivialMessage(message);
      spUtil.simulateFakeFormSubmitForAutoComplete('widget-form', $scope.data.f._fields);
      $timeout(clearStatus, 2000);
    }
  }

  var ctrl = this;
  // switch forms
  var unregister = $scope.$on('$sp.list.click', onListClick);
  $scope.$on("$destroy", function() {
    unregister();
  })

    function _save() {
        var primaryAction = $scope.getPrimaryAction();
    if (primaryAction)
      $scope.triggerUIAction(primaryAction);
    }

    function onListClick(evt, arg) {
        spUtil.clearMessages();
        if ($scope.data.table === 'sys_attachment') {
            if (arg.sys_id && arg.sys_id != -1)
                $location.url('/sys_attachment.do?sys_id=' + arg.sys_id);
        } else
        loadForm(arg.table, arg.sys_id);
    }

  function loadForm(table, sys_id) {
    var f = {};
    $scope.data.table = f.table = table;
    $scope.data.sys_id = f.sys_id = sys_id;
    angular.extend(f,$scope.data.f);
    $scope.data.f.ui_scripts = [];
    $scope.data.f._formatters = {};
    $scope.data.f.policy = [];
    $scope.data.f.validation_scripts = [];

    return $scope.server.update()
            .then(setupAttachmentHandler)
            .catch(function (e){
              angular.extend($scope.data.f,f);
            });
  }

  function openRelatedList(e, queryString) {
    // todo: Open this in a modal
    $location.search(queryString);
    e.preventDefault();
  }

  function closeContextDropdownMenu(toggleButton) {
    var dropdownSpan = $(toggleButton).closest('span.dropdown');
    if (dropdownSpan && dropdownSpan.hasClass('open')) {
      dropdownSpan.removeClass('open');
      toggleButton.setAttribute('aria-expanded', false);
    }
  }

  $scope.$on('spModel.fields.rendered', function() {
    if (ctrl.panels)
      ctrl.panels.removeClass('shift-out').addClass('shift-in');
    var toggleButton = document.getElementById('adminMenu');
    if (!toggleButton)
      return;
    var dropdownMenu = toggleButton.nextElementSibling;
    toggleButton.addEventListener('keydown', function(event) {
      if (event.key === 'Tab')
          closeContextDropdownMenu(toggleButton);  
    });

    if (dropdownMenu) {
      dropdownMenu.addEventListener('focusout', function(event) {
          if (!dropdownMenu.contains(event.relatedTarget))
              closeContextDropdownMenu(toggleButton);
      });
    }
  });

    var g_form;
    function initForm(gFormInstance) {
              $scope.$evalAsync(function() {
             if ($('#widget-form').parents('.modal').length) {
                $scope.embeddedInModal = true;
             }
        })

        if (gFormInstance.getTableName() == $scope.data.f.table){
            g_form = gFormInstance;
            spNavStateManager.register($scope.data.table, _save, g_form);
            $scope.isPageReady = true;
            $timeout(function() {
                $rootScope.$emit('spModel.gForm.rendered', g_form);
            }, 175);
        }
    }

  $scope.$on('spModel.gForm.initialized', function(e, gFormInstance) {
        initForm(gFormInstance);
  });

    $scope.$on('spModel.gForm.env.created', function(e, gFormInstance) {
        initForm(gFormInstance);
  });

    // update the comments or worknotes based on activity stream
    $scope.$on("activity_stream_is_changed", function(event, data) {
        if (g_form && g_form.hasField(data.fieldName)) {
            g_form.setValue(data.fieldName, data.input);
            if (data.fieldToClear != "" && g_form.hasField(data.fieldToClear))
                g_form.setValue(data.fieldToClear, "");
        }
    })

  // Show or hide related lists
  $scope.$watch('data.f._related_lists', function() {
    $scope.data.hideRelatedLists = hideRelatedLists();
  }, true);

    $scope.hideDuplicateSaveAction = function (item) {
        if (!$scope.data.advancedUIEnabled)
            return true;
        return ($scope.data.advancedUIEnabled && item.sys_id !== "432ace8b0a0a0b34006b02832660c894" && item.sys_id !== "42e780d40a0a0b34007e0d4a52d33405");
    };

  function hideRelatedLists() {
    if (!$scope.data.f._related_lists)
      return true;
    if ($scope.options.hideRelatedLists == true)
      return true;
    if ($scope.data.sys_id == '-1')
      return true;
    // If all related lists are visible=false then hide
    if ($scope.data.f._related_lists.length > 0) {
      for (var i in $scope.data.f._related_lists) {
        var list = $scope.data.f._related_lists[i];
        if (list.visible) {
          return false;
        }
      }
    }
    return true;
  }

  // DEF0523212 - update attachment count in related lists when attachments are updated
  if ($scope.data.f._related_lists) {
    var attachmentsPosInRelatedLists = $scope.data.f._related_lists.findIndex((rl) => {
      return rl.table === 'sys_attachment';
    });

    $scope.$on('sp.attachments.recount', function(e, attachmentsLength) {
      if (attachmentsPosInRelatedLists != undefined && attachmentsPosInRelatedLists != -1)
        $scope.data.f._related_lists[attachmentsPosInRelatedLists].count = attachmentsLength;
    });
  }

  function clearStatus() {
    $scope.status = "";
  }

  function setupAttachmentHandler() {
    $scope.attachmentHandler = new nowAttachmentHandler(appendDone, appendError);

        $scope.$evalAsync(function() {
            $scope.attachmentHandler.setParams($scope.data.table, $scope.data.f._attachmentGUID, 1024 * 1024 * $scope.data.maxAttachmentSize);
        });

    $scope.$on('dialog.upload_too_large.show', function(e) {
      $log.error($scope.data.largeAttachmentMsg);
      spUtil.addErrorMessage($scope.data.largeAttachmentMsg);
    });
  }
  setupAttachmentHandler();

  function appendDone() {
    // don't know here whether upload succeeded, so can't show msg either way
    $scope.$broadcast("sp.attachments.update", $scope.data.f._attachmentGUID);
    spUtil.retrieveSessionMessages();
  }

  function appendError(error) {
    $scope.errorMessages.push(error);
    spUtil.addErrorMessage(error.msg + error.fileName);
  }

  if ($scope.data.f.title) {
      $scope.$emit('sp.widget-modal.set-aria-label', $scope.data.f.title);
  }

  $scope.cancel = function(){
    $scope.$parent.$dismiss();
 
    }

//
 var selectedRows;

  spUtil.get("agora-edit-refdata-table", {
                columns: c.data.tableColumns,
                selectedRows: c.data.selectedRows,
                changeType: 'Edit',

            }).then(function(response) {
     
                c.data.editChangeReqDataTableWidget = response;
            });


}


Server side:

// form functionality - URL parameter driven
(function($sp, input, data, options, gs) {
  /* "use strict"; -linter issues */
  // populate the 'data' variable

    data.attachmentUploadSuccessMsg = gs.getMessage("Attachment upload was successful");
    data.recordAddedMsg = gs.getMessage("Record Added");
    data.updatedMsg = gs.getMessage("Record Updated");
    data.exportPDFMsg = gs.getMessage("Export to PDF");
    data.exportPDFLandMsg = gs.getMessage("Export to PDF (landscape)");
    data.addAttachmentMsg = gs.getMessage("Add an attachment");
    data.supportedAttachmentExtensions = gs.getProperty("glide.attachment.extensions", '');
    data.maxAttachmentSize = parseInt(gs.getProperty("com.glide.attachment.max_size", 1024));
    data.advancedUIEnabled = (gs.getProperty("glide.ui.advanced") == "true");
    data.closeWindowMsg = gs.getMessage("Close Window");
    if (isNaN(data.maxAttachmentSize))
        data.maxAttachmentSize = 24;
    data.largeAttachmentMsg = gs.getMessage("Attached files must be smaller than {0} - please try again", "" + data.maxAttachmentSize + "MB");

    data.isAdmin = gs.hasRightsTo('sp/configure.all/execute', null);
    data.emptyStateTemplate = options.empty_state_template;
    var isPopup = false;

    function updateEsToggle() {
        var scriptFields = getServerScriptFields(input);
        for (var i = 0; i < scriptFields.length; i++) {
        var scriptField = scriptFields[i];
            var isToggleValueSaved = GlideSystemUtilScript._getScriptErrorWithToggle(scriptField.value, input.scope, data.table, input.sys_id, input.esLatestVersion);
            if (isToggleValueSaved != null) {
                    gs.addErrorMessage(gs.getMessage("Could not save record because of a compile error: {0}", isToggleValueSaved));
                    return true;
            }  
        }
        return false;
    }

    if (input) {
        data.table = input.table;
        data.sys_id = input.sys_id;
        data.view = input.view;
    if (input.preventUrlUpdateOnSubmit)
      data.preventUrlUpdateOnSubmit = input.preventUrlUpdateOnSubmit;
        var result = {};

        if ((input.sys_id != '-1' || data.sys_id != '-1') && input.f && input.f._fields && input.isInsert) {
            var hasError = updateEsToggle();
            if (hasError)
          return;
        }

        if (input._fields) {
            result = $sp.saveRecord(input.table, input.sys_id, input._fields);
            data.sys_id = result.sys_id;
        }

        if (input.sys_id == '-1')
            data.isNewRecord = true;
        if (input.isPopup === true)
            isPopup = true;
    } else {
        data.table = options.table || $sp.getParameter("t") || $sp.getParameter("table") || $sp.getParameter("sl_table");
        data.sys_id = options.sys_id || $sp.getParameter("sys_id") || $sp.getParameter("sl_sys_id");
        if (!data.sys_id && options.sys_id_required != "true")
            data.sys_id = "-1";
        data.view = options.view || $sp.getParameter("view") || $sp.getParameter("v"); // no default
    }

    if (isPopup && gs.getProperty("glide.service_portal.reference.use_sys_popup_view", "false") == "true") {
        options.hideRelatedLists = true;
        options.disableUIActions = "true";
    }
    data.hideRelatedLists = options.hideRelatedLists || (input && input.hideRelatedLists) || false;
    data.disableUIActions = options.disableUIActions === "true" || !!(input && input.disableUIActions);

    data.query = (input && input.query) ? input.query : ($sp.getParameter("query") || options.query || "");
    data.f = {};
    if (!data.table)
        return;

    // Form widget is not a supported way to view an attachment
    if (data.table == "sys_attachment") {
        data.tableUnsupported = true;
        return;
    }

/*  if (!GlideTableDescriptor.isValid(data.table))
        return;*/

    if (!data.sys_id)
        return;

   var rec = "";//$sp.getRecord(data.table, data.sys_id);////////////////changed here
  if(!rec){
        var gr = new GlideRecord(data.table);
        if(gr.get(data.sys_id)){
            rec=gr;
        }else{
            rec=gr;
        }
    }
    //var rec = $sp.getRecord(data.table, data.sys_id, true);

    if (data.sys_id != "-1" && !rec.canRead())
        return; // can't see requested record

    if (data.sys_id == "-1" && !rec.canCreate())
        return; // can't create a new record

    data.isValid = rec.isValid() || data.sys_id == "-1";
    if (!data.isValid)
        return;

    data.table = rec.getRecordClassName();
    //data.tableHierarchy = GlideDBObjectManager.getTables(data.table).toArray().join();
    data.canWrite = rec.canWrite();
    var hasRecordAccess = data.sys_id == "-1" ? rec.canCreate() : data.canWrite;
    /* data.canAttach = !options.omitAttachmentButton && hasRecordAccess && gs.hasRole(gs.getProperty('glide.attachment.role')) && !GlideTableDescriptor.get(data.table).getED().getBooleanAttribute("no_attachment")*/;
    data.f = $sp.getForm(data.table, data.sys_id, data.query, data.view, isPopup);

    if (data.f && data.f._fields) {
        for (var key in data.f._fields) {
            if ((data.f._fields[key].type === 'script' || data.f._fields[key].type === 'script_plain') && !data.f._fields[key].attributes.client_script) {
        if (typeof data.esLatestVersion === 'undefined')
                  data.esLatestVersion = data.sys_id == "-1" || $sp.shouldUseESLatest(data.table, data.sys_id);
                data.f._fields[key].useEsLatest = data.esLatestVersion;
            }
        }
    }
   
    function getServerScriptFields(inputData) {
        var fields = [];
        if (inputData.f && inputData.f._fields) {
            for (var fieldName in inputData.f._fields) {
                var field = inputData.f._fields[fieldName];
                if ((field.type === 'script' || field.type === 'script_plain') && !field.attributes.client_script)
                    fields.push(field);
            }
        }
        return fields;
    }

    // PRB1335036: show appropriate message when record is in cross app scope
    data.f.outOfScope = data.table.indexOf(gs.getCurrentScopeName()) == -1;
//!rec.isInSelectedScope();
    // Populate scope labels only when needed
    if (data.f.outOfScope) {
        data.f.recordScopeLabel = gs.getScopeLabelByRecordId(rec.getUniqueValue());
        data.f.currentScopeLabel = gs.getCurrentApplicationName();
    }
  var policies = data.f.policy || []
    policies.forEach(function(policy, index){
    if (policy['is_ui_data_policy']) {
      policies[index].onload = true;
    }
  })
    // Activity formatter is hardcoded to set specific options
    for (var f in data.f._formatters) {
        var fm = data.f._formatters[f];
        if (fm.formatter == "activity.xml") {
            fm.hardcoded = true;
            fm.widgetInstance = $sp.getWidget('widget-ticket-conversation',
                                                                {table: data.table,
                                                                 sys_id: data.sys_id,
                                                                 includeExtended: true,
                                                                 hideAttachmentBtn: true,
                                                                 title: "${Activity}",
                                                                 use_dynamic_placeholder: true,
                                                                 btnLabel: "${Post}"});
        } else if(fm.formatter == "com_glideapp_servicecatalog_veditor" || fm.formatter == "com_glideapp_questionset_default_question_editor") {
            var qsConfig = $sp.getValue('quick_start_config');
            if (qsConfig)
                qsConfig = JSON.parse(qsConfig)[0];
            fm.widgetInstance = $sp.getWidget(fm.widget, {table: data.table,
                                                        sys_id: data.sys_id,
                                                        readonly_variable_editor: qsConfig ? qsConfig.readonly_variable_editor : 'false'});
        } else
            fm.widgetInstance = $sp.getWidget(fm.widget, data);
    }



///////////////////

  var sysID = $sp.getParameter('sys_id');
   var table = $sp.getParameter("table");
 // gs.info('table--'+table);
 // gs.info('tableid--'+sysID);


     
var changeRequestSysid =$sp.getParameter('sys_id');
//gs.info("sys_idline231: "+ changeRequestSysid);
var selectRowVariable ="01514d0b976be290dd4d3ace2153af83";
// 01514d0b976be290dd4d3ace2153af83
var gr1 = new GlideRecord("question_answer");
//gr.addEncodedQuery('table_sys_id=e338319c97f7a610dd4d3ace2153aff9^question=fb6262219717e2107f6e3911a153af88');
gr1.addEncodedQuery("table_sys_id=" + changeRequestSysid + "^question=" + selectRowVariable);
gr1.query();

if (gr1.next()) {
    data.selectedRows =JSON.parse(gr1.getValue('value'));
 //.info('selectedrowsline241---'+data.selectedRows);
}
   
/*   var recordProducerId = $sp.getParameter("cat_item_id");
   var gr = new GlideRecord('x_roho_agora_agora_change_request');
  if (gr.get(data.sys_id)) {  
   data.requesttype=gr.getValue('request_type');
}*/

var a;
var obj;
var tableName; // Declare in global scope

  var crtable= new GlideRecord(table);
  if (crtable.get(sysID)) {
 a = crtable.getValue('reference_data');}
   


var ctrlPanelGr = new GlideRecord("yyyyyyyyy");
ctrlPanelGr.addQuery("category=Entity");
ctrlPanelGr.addQuery("value", "CONTAINS", a);
ctrlPanelGr.query();

if (ctrlPanelGr.next()) {
    obj = JSON.parse(ctrlPanelGr.getValue("value"));
    tableName = obj[a]; // Corrected variable name
}

var attributeMapping = getAttributeMapping();    
data.tableColumns = getTableColumns();

function getAttributeMapping() {
    var obj = {};
    var ctrlPanelGr = new GlideRecord("yyyyy");
    ctrlPanelGr.addEncodedQuery("category=Attributes^table=" + tableName);
    ctrlPanelGr.setLimit(1);
    ctrlPanelGr.query();

    if (ctrlPanelGr.next()) {
        obj = JSON.parse(ctrlPanelGr.getValue("value"));
    }
    return obj;
}

function getTableColumns() {
    var tableColumnsArr = [];

    var tableGr = new GlideRecord("sys_dictionary");
    tableGr.addEncodedQuery("elementNOT INsys_created_on,sys_id,sys_mod_count,sys_updated_by,sys_updated_on,sys_created_by^name=" + tableName);
    tableGr.query();
    while (tableGr.next()) {
        tableColumnsArr.push({
            label: attributeMapping[tableGr.getValue("element")] ? attributeMapping[tableGr.getValue("element")] : tableGr.getValue("column_label"),
            name: tableGr.getValue("element")
        });
    }

    tableColumnsArr.forEach(function(t) {
        var refAttributeGr = new GlideRecord("yyyyy");
        refAttributeGr.addEncodedQuery("resource_type=Asset^type=Data Attribute^name=" + t.label);
        refAttributeGr.setLimit(1);
        refAttributeGr.query();
        if (refAttributeGr.next()) {
            t.hint = refAttributeGr.getValue("description");
            t.isHierarchy = refAttributeGr.getValue('is_hierarchy') == 1;
            t.level = parseInt(refAttributeGr.getValue('level'));
        }
    });

    return tableColumnsArr;
}


data.tableColumns = getTableColumns();
data.editChangeReqDataTableWidget = $sp.getWidget("edit-refdata-table");
data.entityHierachyWidget = $sp.getWidget("entity-hierarchy-table");
data.rework=$sp.getWidget('rework');
data.withdraw=$sp.getWidget('selected_data');
data.cancel=$sp.getWidget('cancel');
   
})($sp, input, data, options, gs);


//new function added
function getRecordScopeLabel(table){
    var grObject = new GlideRecord("sys_db_object");
    grObject.addQuery("name="+table);
    grObject.setLimit(1);
    grObject.query();
    if(grObject.next()){
        return grObject.sys_scope.getDisplayValue();
    }

}

function currentApplication(){
    var grScope = new GlideRecord("sys_scope");
    grScope.addQuery("scope="+gs.getCurrentScopeName());
    grScope.setLimit(1);
    grScope.query();
    if(grScope.next()){
        return grScope.name.getDisplayValue();
    }
}

function tableHierarchy(tableName){
    var hierarchy = new GlideTableHierarchy(tableName);
    return hierarchy.getHierarchy().join();

}



















1 REPLY 1

Ravi Gaurav
Giga Sage
Giga Sage

 

Thanks for pasting all that — I can see exactly what’s happening.
When you clone the Form widget into a scoped app, attachments usually don’t show up for two reasons:

Why Attachments Fail in Scoped Clone

  1. Cross-scope issue

    • The out-of-box Form widget uses the nowAttachmentHandler service, which is in the global scope.

    • If you clone the widget into a custom scope, your version may not have the right access to call it.

  2. Attachment params not wired up

    • The <sp-attachment-manager> directive needs:

       
      <sp-attachment-manager table="::data.table" sys-id="data.f._attachmentGUID" omit-edit="::!data.canAttach"> </sp-attachment-manager>
    • If data.f._attachmentGUID is blank or data.canAttach is false, no attachments render.

 

What to Check / Fix

1. Ensure your scoped widget has access to nowAttachmentHandler

  • In the client controller you already have:

     
    function($rootScope, $scope, ..., nowAttachmentHandler, ...)
  • That injection will break if the scoped app does not include the dependency.

  • Solution:

    • In your scoped widget, make sure "Accessible from" is set to All application scopes (not just this scope).

    • Or create a Dependency record in sys_script_include to allow cross-scope calls.

 

2. Verify you are passing correct sys_id

  • In your controller:

     
    var tableId = $scope.data.sys_id != -1 ? $scope.data.sys_id : ($scope.data.f ? $scope.data.f._attachmentGUID : -1);
  • Make sure data.sys_id is set correctly in the server script. If this resolves to -1, the widget will think you are on a “new record” and won’t render attachments.

Try hard-coding temporarily:

 

 
<sp-attachment-manager table="x_your_scope_custom_table" sys-id="{{::data.sys_id}}"> </sp-attachment-manager>

 

If that works → your problem is in how data.f._attachmentGUID is populated.

 

3. Set data.canAttach correctly

  • In your server script, you currently commented this:

     
    /* data.canAttach = !options.omitAttachmentButton && hasRecordAccess && ... */
  • If data.canAttach is undefined or false, <sp-attachment-manager> will render nothing.

  • Make sure to set it explicitly:

     
    data.canAttach = true;

4. Debugging Tip

From your browser console (in the portal):

angular.element(document.querySelector("sp-attachment-manager")).isolateScope().attachments

This should show you if the directive has any attachments loaded.

--------------------------------------------------------------------------------------------------------------------------


If you found my response helpful, I would greatly appreciate it if you could mark it as "Accepted Solution" and "Helpful."
Your support not only benefits the community but also encourages me to continue assisting. Thank you so much!

Thanks and Regards
Ravi Gaurav | ServiceNow MVP 2025,2024 | ServiceNow Practice Lead | Solution Architect
CGI
M.Tech in Data Science & AI

 YouTube: https://www.youtube.com/@learnservicenowwithravi
 LinkedIn: https://www.linkedin.com/in/ravi-gaurav-a67542aa/