- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-19-2018 02:05 PM
I am using the slush bucket widget on a portal page so I can use a m2m table to link multiple songs to a gig. I have the songs in in the 'available' bucket and the widget works for me, but I am struggling to work out how to make the 'save' work like it would in the CMS through the edit option.
I am trying to decide if I should create a save button on the widget or if I should have the save button on the record form do the save once the songs are added to the gig.
If I do the slush widget (which I have been attempting to do now) I have attempted to take some of the code from the record widget save button but I am struggling with that. Which is what made me think about using that button to save the details in the slush widget.
Any suggestions on the best way to tackle this?
I looked at the list collector option as a variable on the form, but I couldn't work out how to make the songs save in the related list as I needed.
Below is the widget code I have so far
html
<div>
<h4>Select songs for this gig</h4>
<button type="button" class="btn btn-primary action-btn">Save songs</button>
<button ng-if="getPrimaryAction()" type="submit" ng-click="triggerUIAction(getPrimaryAction())" ng-disabled="submitting" class="btn btn-primary action-btn pull-right ng-scope" gsft_id="{{::action.sys_id}}">Save selections<!-- ngIf: saveButtonSuffix --><span ng-if="saveButtonSuffix" class="ng-binding ng-scope">(Ctrl + s)</span><!-- end ngIf: saveButtonSuffix --></button>
<div class="row">
<div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">${Select from below}</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: item.used}"
class="list-group-item">
<div as-sortable-item-handle>
<span>{{item.u_song_title.display_value}}</span>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">${In gig}</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.u_song_title.display_value}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div>
</div>
</div>
CSS
.as-sortable-placeholder {
background-color: #eee;
}
.slush-scrollable {
height: 240px;
overflow-y: scroll;
overflow-x:hidden;
}
.panel > .list-group:last-child .list-group-item:last-child {
border-bottom-width: 1px;
border-bottom-style: solid;
border-radius: 0;
}
.used {
max-height: 0;
overflow: hidden;
padding: 0;
border: none;
}
.available > .list-group-item {
transition: all 1s;
}
.btn-form-menu {
vertical-align: inherit;
padding: inherit;
background: none;
}
Client
function($rootScope, $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;
})
}
function _save() {
var primaryAction = $scope.getPrimaryAction();
if (primaryAction)
$scope.triggerUIAction(primaryAction);
}
$scope.triggerUIAction = function(action) {
if ($scope.data.disableUIActions && !action.primary) {
return;
}
}
}
server
(function () {
// grab the filtered songs
data.all = [];
var filterQuery = "u_perform_statusIN1,2,3^u_song_status=2";
var gr = new GlideRecord('x_120100_band_songs');
gr.orderBy('u_song_title');
gr.addEncodedQuery(filterQuery);
gr.query();
while (gr.next()) {
var t = $sp.getRecordElements(gr, 'u_song_title,sys_id');
data.all.push(t);
}
})();
Solved! Go to Solution.
- Labels:
-
Service Portal Development
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-21-2018 05:31 AM
Hi Walshy,
In your server script for the input:
addSong.songs = input.songs[indx]
should be
addSong.songs = input.songs[indx].sys_id.value
according to your screenshot of the Object and if the "songs" field is a reference field on the m2m table.
Also as a side note to clear things up a little in your comments of your Client Script in the server.get() method. (Hopefully you don't mind)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-20-2018 03:22 PM
For future reference, if you wanted to just use the "Save" button from the record form you can do something like below in the client script of the slush bucket widget.
If I'm not mistaken it should be possible to use this snippet to listen for the submission of the record:
$rootScope.$on('sp.form.submitted', function(evt, data){
})
Then from that kick off the c.saveMySongs() code to save the slush bucket stuff. Together would look like this:
$rootScope.$on('sp.form.submitted', function(evt, data){
c.saveMySongs()
})
Summary:
That snippet just listens for when the form is submitted and when it is also perform the code code within the listener.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-20-2018 10:35 PM
Hi,
I believe you want to have a list collector element instead on glidelist element, which servicenow renders when there is a list collector on a catalog item.
I have tried this and working fine, I have tried below approach.
- hide the actual variable via a client script (UI type of script would be service portal)// so this will hide actual variable on portal.
- Create new variable on catalog item/ record produce as type : UI macro and choose your widget.
so now, on portal, your widget would display and on native view normal list collector would be visible
Next step, in you client controller, you would be able to use g_form api like below
$scope.page.g_form();
Whenever someone is adding some value from left to right, just keep setting the value to hidden variable like below
$scope.page.g_form().setValue('your hidden variable', 'you you moved from left to right');
I hope this would help.