Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

Widget returning [object Object]

Winston
Tera Guru

Hey everyone, 

I'm a little at my wits end here. I've trying to use the OOB Slush bucket widget on a catalog form to have it pull multiple values from a table and then have it fill to a variable (which will be hidden) on the same form.

Everything is working perfect, BUT (there's always a but) the values are passing from the widget as [object object].

find_real_file.png

Here's how i'm filling the selected values from the client script of the widget and filling into the form variable named, test.

$scope.$watch('c.selected.toString()', function(newVal, oldVal) {
	$scope.page.g_form.setValue('test', newVal);
      });

Here is the full Client Script:

// sample use of ng-sortable
function($scope) {
	var c = this;
	c.selected = [];
	
	// ng-sortable clone means cannot reorder
	c.availableAs = {
		itemMoved: function (event) {
			event.source.itemScope.item.used = true;
		},
		clone: true // clone this side
	}

	c.selectedAs = {
		itemMoved: function (event) {
			// moved back to available
			var item = event.source.itemScope.item;
			moveToAvailable(item);
			removeItem(c.data.all, item);
		},
		dragStart: function () {
			c.availableAs.clone = false;
		},
		dragEnd: function () {
			c.availableAs.clone = true;
		}
	}

	// double moves from Available to Selected
	c.onDblClick = function(item) {
		var t = angular.copy(item);
		item.used = true; // original is now used
		c.selected.push(t);
	}

	// double on selected removes and unsets Available used
	c.onSelDblClick = function(item) {
		moveToAvailable(item);
		removeItem(c.selected, item);
	}

	function removeItem(array, item) {
		var n = array.indexOf(item);
		if (n !== -1)
			array.splice(n, 1);		
	}
	
	function moveToAvailable(item) {
		var t = item.sys_id.value;
		angular.forEach(c.data.all, function(target) {
			if (target.sys_id.value == t)
				target.used = false;
		})		
	}
	
		$scope.$watch('c.selected.toString()', function(newVal, oldVal) {
			$scope.page.g_form.setValue('test', newVal);
      });
}

Here is the server script:

(function () {
	// grab names of available dependencies
	data.all = [];
	var fieldnames = "sys_id,label";
	var gr = new GlideRecord('sys_choice');
	gr.orderBy(fieldnames);
	gr.query();
	while (gr.next()) {
		var t = $sp.getRecordElements(gr, fieldnames);
		data.all.push(t);
	}
})();
11 REPLIES 11

Here's where I'm at now with this. I got it to fill the label into the hidden field by switching

var t = $sp.getRecordElements(gr,"label");

to


var t = gr.label.getDisplayValue();

in the Server Script below:

 (function () {
	// grab names of available dependencies
	data.all = [];
	var gr = new GlideRecord('sys_choice');
	gr.orderBy("label");
	//gr.addQuery('u_sort_value_1', 'Tax Collector FDLIS');
	gr.addQuery('u_sort_value_1', '3');
	gr.query();
	while (gr.next()) {
		//var t = $sp.getRecordElements(gr,"label");
		var t = gr.label.getDisplayValue();
		data.all.push(t);
	}
})();

and I got the label in the buckets to display when I switched the HTML from

<span>{{item.label.display_value}}</span>

to

<span>{{item}}</span>

 

It was showing the correct labels in the buckets and filling the labels in the hidden field, but then it wasn't removing the values from the available bucket when they were dropped into the selected bucket. 

Until I switched

ng-class="{used: item.used}"

to 

ng-class="{used: used}" in the HTML

and updated the client script from 

c.availableAs = {
itemMoved: function (event) {
event.source.itemScope.item.used = true;
},
clone: true // clone this side
}

to

c.availableAs = {
itemMoved: function (event) {
event.source.itemScope.used = true;
},
clone: true // clone this side
}

 

So now it's pulling the values out of the Available bucket into the Selected, but when I try to remove the value from the selected and put it back into the available the value just disappears (it does take the value out of the hidden field though so that's good.) 

find_real_file.png

find_real_file.png

 

Below are the full scripts i'm using currently:

HTML Template:

<div>
  <h4>Test Roles</h4>
  <div class="row">
    
   <div class="col-sm-4">
     <div class="panel panel-default">
       <div class="panel-heading">
         <h4 class="panel-title">${Available}</h4>
         </div>
       <div class="available list-group slush-scrollable"
            as-sortable="c.availableAs"
            ng-model="c.data.all">
         <div ng-repeat="item in c.data.all | filter:c.search"
              as-sortable-item
              ng-dblclick="c.onDblClick(item)"
              ng-class="{used: used}"
              class="list-group-item">
           <div as-sortable-item-handle>
             <span>{{item}}</span>
             </div>
           </div>
         </div>
       </div>
     </div>
    
    <div class="col-sm-4">
      <div class="panel panel-default">
        <div class="panel-heading">
          <h4 class="panel-title">${Selected}</h4>
          </div>
        <div class="list-group slush-scrollable" as-sortable="c.selectedAs" ng-model="c.selected">
          <div ng-repeat="item in c.selected"
               as-sortable-item
               ng-dblclick="c.onSelDblClick(item)"
               class="list-group-item">
            <div as-sortable-item-handle>
              <span>{{item}}</span>
              </div>
            </div>
          </div>
        </div>
      </div>
   	</div>
  <div>
   Drag needed roles to "Selected" bucket.<br/>
    </div>
  
  </div>
          
          

Client Script:

// sample use of ng-sortable
function($scope) {
	var c = this;
	c.selected = [];
	
	// ng-sortable clone means cannot reorder
	c.availableAs = {
		itemMoved: function (event) {
			event.source.itemScope.used = true;
		},
		clone: true // clone this side
	}

	c.selectedAs = {
		itemMoved: function (event) {
			// moved back to available
			var item = event.source.itemScope.item;
			moveToAvailable(item);
			removeItem(c.data.all, item);
		},
		dragStart: function () {
			c.availableAs.clone = false;
		},
		dragEnd: function () {
			c.availableAs.clone = true;
		}
	}
/*
	// double moves from Available to Selected
	c.onDblClick = function(item) {
		var t = angular.copy(item);
		used = true; // original is now used
		c.selected.push(t);
	}

	// double on selected removes and unsets Available used
	c.onSelDblClick = function(item) {
		moveToAvailable(item);
		removeItem(c.selected, item);
	}
*/
	
	function removeItem(array, item) {
		var n = array.indexOf(item);
		if (n !== -1)
			array.splice(n, 1);		
	}
	
	function moveToAvailable(item) {
		var t = item.sys_id.value;
		angular.forEach(c.data.all, function(target) {
			if (target.sys_id.value == t)
				target.used = false;
		})		
	}
	
	$scope.$watch('c.selected.toString()', function(newVal, oldVal) {
			$scope.page.g_form.setValue('test', JSON.stringify(c.selected));
      });
}

Server Script:

(function () {
	// grab names of available dependencies
	data.all = [];
	var gr = new GlideRecord('sys_choice');
	gr.orderBy("label");
	//gr.addQuery('u_sort_value_1', 'Tax Collector FDLIS');
	gr.addQuery('u_sort_value_1', '3');
	gr.query();
	while (gr.next()) {
		//var t = $sp.getRecordElements(gr,"label");
		var t = gr.label.getDisplayValue();
		data.all.push(t);
	}
})();

Allen Andreas
Tera Patron

Lol...I'm not sure what is going on here, but you've posted something similar to this 3 times and Mike has replied ...now 3 times?

So this one, then these 2 below:

https://community.servicenow.com/community?id=community_question&sys_id=12d31299dbfc18902be0a851ca96...

https://community.servicenow.com/community?id=community_question&sys_id=73d40951dbb494902be0a851ca96...

It's recommend to really keep the communication in to one thread so you can get help and more people can assist, otherwise, it's as if Mike is just replying to each thread every few hours they're posted, haha.

Thanks!


Please consider marking my reply as Helpful and/or Accept Solution, if applicable. Thanks!

The problem is that users don’t provide same info on old post instead they just keep creating new questions. I would have replied to old post if same info was added to old post. I have seen few users who have done same and once they get the answer they delete all questions.

Ouch...


Please consider marking my reply as Helpful and/or Accept Solution, if applicable. Thanks!

Yes sir, understood. Won't happen again!