- 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-19-2018 02:58 PM
If you want to use your "Save songs" button:
1. add to
<button type="button" class="btn btn-primary action-btn">Save songs</button>
ng-click function and you really do not need the next button; So for example ng-click = c.saveMySongs()
2. in controller add code for your function
c.saveMySongs = function(){
//pass your data to server in order to save
c.server.get({
action:'saveSongs',
songs: c.selected,
gig_sysID://add here your gig sys_id
//pass whatever you need here
}).then(function(response){
// add some actions
});
}
3. on server script add GlideRecord to save records
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-19-2018 04:58 PM
Hey Malgorzata
Thanks for that I will dive in and see how I go, makes sense, lets just see if I have the capacity.
Cheers!
Cam.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-20-2018 12:21 PM
I've gone through this and I am failing, I figured I needed to save both the gig and the song to the m2m table to create the relationship.
Below is what I have tried to do.
HTML
<div>
<h4>Add songs here <button type="button" class="btn btn-primary action-btn pull-right" ng-click="c.saveMySongs()">Save songs</button></h4>
<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>
CLIENT
function($rootScope, $scope, spUtil) {
var c = this;
c.selected = [];
// 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 click moves from left bucket to right
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;
})
}
c.saveMySongs = function(){
//pass the data to server in order to save
c.sever.get(
{
action:'saveSongs',
songs: c.selected,
gigsys_ID: data.gigSysId
}
)
.then(function(r){
//pass whatever you need here
c.data.sys_id = r.data.sys_id;
c.data.number = r.data.number;
c.data.u_song_title = r.data.u_song_title;
});
}
}
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);
}
// get the sys_id of the current gig from the URL
data.gigSysId = $sp.getParameter("sys_id");
// save the song to the gig in the m2m table
if (input){
var addSong = new GlideRecord('x_120100_band_m2m_set_list');
if (addSong.get(input.saveMySongs)) {
if (input.action == 'saveSongs') {
data.songs = {};
$sp.getRecordValues(data.title, sys_id, "u_song_title, sys_id");
}
}
}
})();
Anyone with any ideas on where I am going wrong would be appreciated.
Thank you!
Cam
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-20-2018 02:39 PM
1. could you print out
console.log(input.songs); // should be your list of sys_ids
console.log(input.gigsys_ID); // sys_is of your record
2. since you have
data.gigSysId
you do not need to pass this from controller
3. when you retrieve your data on server side you should have something similar to:
if (input.action == 'saveSongs' ){
for(var indx in input.songs){
var addSong = new GlideRecord('x_120100_band_m2m_set_list');
addSong.initialize();
addSong.gig=data.gigSysId;
addSong.song=input.songs[indx];
addSong.insert();
}
}
after you create new relationships between songs and gig you can return something so you will know that it was successful
Let me know if this makes sense to you