Unable to access td element of MRVS in SP Variable Editor on Service Portal

Community Alums
Not applicable

Below is a MRVS in SP Variable Editor Widget in Service Portal.

But document.getElementsByTagName, ByID,... all returning null when accessing it via client.

I need to access the innerHTML of cells and do styling based on match.

 

Abdullah10_0-1706816717753.png

 

1 ACCEPTED SOLUTION

Nick Parsons
Mega Sage

Can you share how you're trying to select the elements and also share what the HTML structure is of the MRVS in the variable editor is. Also, perhaps you're running your code that tries to select the HTML td elements before it's been loaded into the DOM. Perhaps you need to add a delay before you try and read the elements (using a MutationObserver can be used to determine when the content has loaded, or setTimeout for an arbitrary delay).

Do be aware that trying to change elements and styles via DOM manipulation is not recommended, as ServiceNow could change how things are structured in a future upgrade.

View solution in original post

4 REPLIES 4

Nick Parsons
Mega Sage

Can you share how you're trying to select the elements and also share what the HTML structure is of the MRVS in the variable editor is. Also, perhaps you're running your code that tries to select the HTML td elements before it's been loaded into the DOM. Perhaps you need to add a delay before you try and read the elements (using a MutationObserver can be used to determine when the content has loaded, or setTimeout for an arbitrary delay).

Do be aware that trying to change elements and styles via DOM manipulation is not recommended, as ServiceNow could change how things are structured in a future upgrade.

Community Alums
Not applicable

HTML

<div ng-class="{'panel panel-default': !data.hide_container}" ng-if="data.category == 'Oracle Fusion ASaaS ERP Access'" >
  <div  class="panel-heading" ng-if="!data.hide_container">
    <h3 ng-if="data.itemTitle" class="panel-title">{{data.itemTitle}}</h3>
    <h3 ng-if="!data.itemTitle" class="panel-title">${Variables}</h3>
  </div>
  <div ng-class="{'panel-body': !data.hide_container, 'variable-editor': data.hide_container}">
    <sp-model form-model="::data.sc_cat_item" mandatory="[]"></sp-model>
  </div>
 <!-- <div ng-if="c.showSave && c.options.readonly_variable_editor != 'true'" class="panel-footer">
    <button class="btn btn-primary pull-right" name="save" ng-click="c.save()">${Save}</button>
    <span ng-if="validating" style="padding-left:4px">${Validating...}</span>
	  <div style="clear: both;"></div>
  </div>-->
</div>
<div class="workspace-variables" ng-if="::c.hasVariables(data.sc_cat_item._fields) && c.options.isServiceWorkspace">
  <div class="variables">
    <sp-model form-model="::data.sc_cat_item" mandatory="[]"></sp-model>
  </div>
  <div ng-if="c.showSave && c.options.readonly_variable_editor != 'true'">
    <button class="btn btn-primary pull-right" name="save" ng-click="c.save()">${Save}</button>
    <span ng-if="validating" style="padding-left:4px">${Validating...}</span>
	  <div style="clear: both;"></div>
  </div>
</div>
<div ng-if="::!c.hasVariables(data.sc_cat_item._fields)">
  <h4 class="text-a-c">
    {{::c.data.msg}}
  </h4>
 
</div>
<now-message key="Variable saved" value="${Variable saved}"></now-message>

 

Client

function($scope, $document, $rootScope, i18n, spScUtil) {																					
  /* widget controller */
  var c = this;
	c.isSaved = false;
	var parent_g_form = $scope.page.g_form;
	var origActionName;

	//alert(s.length);
	if (!parent_g_form)
		c.showSave = true;
	
	c.getItemId = function () {
		return $scope.data.sc_cat_item ? $scope.data.sc_cat_item.sys_id : -1;
	};
	
	
	

	var g_form;
	$scope.$on('spModel.gForm.initialized', function(e, gFormInstance){
		if (gFormInstance.getSysId() != -1 && gFormInstance.getSysId() != c.getItemId())
			return;
		

		
		if (parent_g_form)
			addSaveHandler();

		g_form = gFormInstance;
		g_form.$private.events.on('submitted', function() {
				if (!c.showSave) {
					c.server.update().then(function() {
						parent_g_form.submit(origActionName);
						c.isSaved = true;
					});
				}
				else {
				c.server.update().then(function() {
				g_form.addInfoMessage(i18n.getMessage('Variable saved'));
				if (c.options.isServiceWorkspace == true) { //Workspace handler
					if (window.parent === window) {
						console.warn("Parent is missing. Is this called inside an iFrame?");
						return;
					}
					window.parent.postMessage({
							messageType: 'IFRAME_MODAL_MESSAGE_TYPE',
							modalAction: 'IFRAME_MODAL_ACTION_CONFIRMED',
							modalId: 'sn-modal-iframe-singleton'
					}, location.origin)
				}
				if (c.data.table == "sc_cart_item")
					$rootScope.$broadcast("$sp.service_catalog.cart.update");
				});
			}
		})
	});

	// Used when embedded as a formatter
	function addSaveHandler() {
		parent_g_form.$private.events.on("submit", function() {
			var actionName = parent_g_form.getActionName();
			// If actionName is none, form has already been re-submitted.
			// No need to submit it the third time.
			if (actionName === 'none') { return false; }

			origActionName = actionName;
			if (c.isSaved) return true;

			if (!spScUtil.isServerValidationDone($scope.data.sc_cat_item._fields)) {
				$scope.validating = true;
				return false;
			}

			if (g_form)
				return g_form.submit();
			return true;
		});
		parent_g_form.$private.events.on("submitted", function() {
			c.isSaved = false;
		});
		//var s = $document[0].getElementsByTagName('td');
	//	alert(s.length);
	}

	c.save = function() {
		var activeElement = $document.activeElement;
		if (activeElement)
			activeElement.blur();
		if (!spScUtil.isServerValidationDone($scope.data.sc_cat_item._fields))
			$scope.validating = true;

		else if (g_form)
			g_form.submit();		
	};
	c.hasVariables = function(fields) {
		if (!fields) 
			return false;
		
		return Object.keys(fields).length > 0;
	}

	//$('h3').hide();
	//	var s = $document[0].getElementById('');
	//alert(JSON.stringify(s))
		
	
		
	
	
	var validationComplete = $rootScope.$on('$sp.service_catalog.form_validation_complete', function() { $scope.validating = false; });
}

I can't see where the problematic document.getElementsByTagName/byId is being used in your client script.

 

Also that appears to be the widget HTML template. I guess once it renders it produces the MRVS using a table? What does that generated HTML look like (as I assume that is what you're trying to access)?
Did you give the setTimeout option a go? Any luck with that?

Community Alums
Not applicable

yes, after giving setTimeout it is capturing td elements and able to get Collection length.

Thanks a lot.