Submit button pops up error alerts on a scoped app

tpeleg
Tera Expert

Hi experts,

 

we cloned the ootb form widget to a scoped app and when using the submit button on a new record (save button) it's inserts a new record to a table but pops up some error alerts:

 

 

tpeleg_0-1734965335673.png

 

here is the HTML code (same as OOB) :

 

<button ng-if="getPrimaryAction()" type="submit" ng-click="triggerUIAction(getPrimaryAction())" ng-disabled="submitting" class="btn btn-primary action-btn pull-right" gsft_id="{{::getPrimaryAction().sys_id ? getPrimaryAction().sys_id : ''}}">${Submit}</button>

 

client and server scripts are same as OOB as well.

when using same button to update existing record, there are no alerts.

 

I believe it's a scoped app issue, so I've tried to change the ActionUtil script include to be accssible from all scopes

tpeleg_1-1734965709055.png

 we still see error alerts, but different:

tpeleg_2-1734965795485.png

 

did someone faced this kind of issue? if yes, what would be the best approach to solve?

 

Thanks,

 

Tomer

14 REPLIES 14

Runjay Patel
Giga Sage

Hi @tpeleg ,

 

Check the function written in widget where it making ajax call GlideAjax('ActionUtils'), just change it to GlideAjax('global.ActionUtils').

 

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

If you found my response helpful, please consider selecting "Accept as Solution" and marking it as "Helpful." This not only supports me but also benefits the community.


Regards
Runjay Patel - ServiceNow Solution Architect
YouTube: https://www.youtube.com/@RunjayP
LinkedIn: https://www.linkedin.com/in/runjay

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

Hi and thank you @Runjay Patel , I've tried to look for this ajax call within the widgets but unfortunately I couldn't find any reference to that

Hi @tpeleg ,

share your full code. The error you are getting that is cross scope and you are either calling script include using ajax or direct from server.

Hi @Runjay Patel Thank you

 

Client

 

function($rootScope, $scope, $timeout, $location, $log, $window, spUtil, nowAttachmentHandler, spAriaUtil, spNavStateManager) {
  $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 !== -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.cancelButton = function() {
    //alert('cancel btn');
		history.back();
  }

  $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.triggerUIAction(primaryAction);
  });
  $scope.$on('$destroy', function() {
    deregister()
  });

  $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) {
        $scope.submitting = true;
        if (!g_form.submit(action.action_name || action.sys_id))
          $scope.submitting = false;
      }
    });
  }

  $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;
    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;
        if (!$scope.data.preventUrlUpdateOnSubmit) {
          var search = $location.search();
          search.sys_id = response.sys_id;
          search.spa = 1;
          $location.search(search).replace();
        }
      } 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();
		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 = [];
    $scope.data.f._ui_actions = [];	
    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();
  }

  $scope.$on('spModel.fields.rendered', function() {
    if (ctrl.panels)
      ctrl.panels.removeClass('shift-out').addClass('shift-in');
  });

	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;
  }

  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();
  }
}

 

Server

 

// 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.maxAttachmentSize = parseInt(gs.getProperty("com.glide.attachment.max_size", 1024));
	data.advancedUIEnabled = (gs.getProperty("glide.ui.advanced") == "true");
	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;

	if (input) {
		data.table = input.table;
		data.sys_id = input.sys_id;
		data.view = input.view;
		var result = {};
		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 || false;
	data.disableUIActions = options.disableUIActions === "true";

	data.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){
		console.log("sysid missing");
		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;
		}
	}




	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 = tableHierarchy(data.table);//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);

	// PRB1335036: show appropriate message when record is in cross app scope
	data.f.outOfScope = data.table.indexOf(gs.getCurrentScopeName()) == -1;//!rec.isInSelectedScope();////////////changed here
	// Populate scope labels only when needed
	if (data.f.outOfScope) {
		data.f.recordScopeLabel = getRecordScopeLabel(data.table); //gs.getScopeLabelByRecordId(rec.getUniqueValue());
		data.f.currentScopeLabel = currentApplication();//gs.getCurrentApplicationName();
	}

	// 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);
	}
})($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();

}

 

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 ng-if="!data.hideRelatedLists">
        <label class="h4" role="heading" aria-level="{{embeddedInModal ? '2' : '3'}}" style="margin: 0">${Related Lists}</label>
        <div style="margin-bottom: 7px; padding-bottom: 7px; border-bottom: 1px solid #f5f5f5;">
          <nav aria-label="${Related Lists}">
            <span ng-repeat="rl in data.f._related_lists" ng-if="rl.visible">
              <a ng-if="rl.type != 'REL'" ng-href="?id=lf&table={{::rl.table}}&filter={{rl.field}}%3D{{data.f.sys_id}}{{rl.filter ? '^' + rl.filter : ''}}&view={{data.f.view}}" ng-click="openRelatedList($event, {id: 'lf', table: '{{::rl.table}}', filter: '{{rl.field}}%3D{{data.f.sys_id}}'})">{{rl.plural}}
                <span class="label label-as-badge label-primary" ng-if="rl.count">{{::rl.count}}</span>
              </a>
              <a ng-if="::rl.type == 'REL'" href="?id=lf&table={{::rl.table}}&relationship_id={{rl.relationship_id}}&apply_to={{rl.apply_to}}&apply_to_sys_id={{rl.apply_to_sys_id}}&view={{::data.f.view}}" ng-click="openRelatedList($event, {id: 'lf', table: '{{::rl.table}}', apply_to: '{{rl.apply_to}}', apply_to_sys_id: '{{rl.apply_to_sys_id}}', relationship_id: '{{rl.relationship_id}}'})">{{rl.label}}
                <span class="label label-as-badge label-primary" ng-if="rl.count">{{rl.count}}</span>
              </a>
              <span ng-if="!$last" class="related-lists-vertical-bar" aria-hidden="true"> | </span>
            </span>
          </nav>
        </div>
      </div>
    </div>

    <div class="panel-footer">
    <button ng-if="getPrimaryAction()" type="submit" ng-click="triggerUIAction(getPrimaryAction())" ng-disabled="submitting" class="btn btn-primary action-btn pull-right" gsft_id="{{::getPrimaryAction().sys_id ? getPrimaryAction().sys_id : ''}}">${Submit} </button>
    <!-- <button ng-click="triggerUIAction(action)" ng-disabled="submitting" ng-repeat="action in getUIActions('button') | filter: hideDuplicateSaveAction" class="btn action-btn" ng-class="::getButtonClass(action)" gsft_id="{{::action.sys_id}}">{{action.name}}</button>-->
      <button ng-click="cancelButton()" ng-disabled="submitting" class="btn action-btn">${Cancel} </button>
      <span>{{status}}</span>
     <!-- <button ng-if="getPrimaryAction()" type="submit" ng-click="triggerUIAction(getPrimaryAction())" ng-disabled="submitting" class="btn btn-primary action-btn pull-right" gsft_id="{{::getPrimaryAction().sys_id ? getPrimaryAction().sys_id : ''}}">${Submit}</button>-->
      <div style="clear: both;"></div>
      <div ng-if="mandatory.length" class="alert alert-info" style="margin-top: .5em" aria-live="polite" aria-atomic="true">
        <span ng-if="mandatory.length > 0">${Required information} </span>
        <span ng-repeat="f in mandatory" class="label sc-field-error-label" ng-bind="f.label"></span>
      </div>
    </div>
  </div>
</div>