How to set/pass values from checkbox field in portal

mballinger
Mega Guru

Hello,

I am working on a portal widget. What I need to do is send data from the HTML to Client to Server Script from a checkbox selection. It is not a complex widget, but I do not know how to work with checkboxes. Having the toggle work real time would also be great without have to use a button to send the data to client/server. Essentially the purpose of this widget is to allow users to manage notifications by turning them on/off from the portal under the users profile. 

If a record exists on the cmn_notif_message table and the Filter is equal to Unsubscribe, I need to default the toggle to true and if it is empty, I need to default the value to false. 

I also need to send the checkbox value back and update the record.

What I have so far:

HTML:

<div class="panel panel-default">
	<table class="table">
	  <thead>
		<tr>
		  <th scope="col">Notification Name</th>
		  <th scope="col">Device</th>
		  <th scope="col">Toggle On/Off</th>
		</tr>
	  </thead>
	  <tbody>
		<tr ng-repeat="obj in c.data.list">
		  <td>{{obj.message}}</td>
		  <td>{{obj.name}}</td>
		  <td><input id="checkbox" type="checkbox" ng-model="toggle"></td>
		</tr>
	  </tbody>
	</table>
</div>

Server Script:

var currentUser = gs.getUserID();
data.list = [];

var gr = new GlideRecord('cmn_notif_message');
gr.addQuery('user', currentUser);
gr.query();
while(gr.next()) {
   var notifObj = {};
   
   notifObj.message = gr.getDisplayValue('notification');
   notifObj.name = gr.getDisplayValue('user');

   data.list.push(notifObj);
}

Thanks!

1 ACCEPTED SOLUTION

Michael Jones -
Giga Sage

You need to track the ID of the record you want to update, create a client function to pass the data, attach it to your checkbox and then update the server code to accept input and take action. Something like this would do the trick: 

HTML: adds a way to track the record id and attaches an onclick and set the toggle based on the current state of the record. 

<div class="panel panel-default">
	<table class="table">
	  <thead>
		<tr>
		  <th scope="col">Notification Name</th>
		  <th scope="col">Device</th>
		  <th scope="col">Toggle On/Off</th>
		</tr>
	  </thead>
	  <tbody>
		<tr ng-repeat="obj in c.data.list">
		  <td>{{obj.message}}</td>
		  <td>{{obj.name}}</td>
		  <td><input id="checkbox" type="checkbox" ng-model="toggle" ng-checked="obj.toggle" ng-click="c.update(obj.sys_id)"></td>
		</tr>
	  </tbody>
	</table>
</div>

Client script: function for the onclick to take the value and pass it back to the server

api.controller=function() {

  var c = this;
	
	c.update = function(sys_id) {
		input = {};
		input.sys_id = sys_id;
		input.action = 'UpdateRec';
		
		c.server.get(input).then(function(r) {
            c.data = r.data;
        });
	};
	
};

Server Script: track the sys_id and current state for the toggle, accept input, update the record. 

(function() {
    var currentUser = gs.getUserID();
    data.list = [];

	//sys_id for the value unsubscribe, at least in my PDI
    var unsubscribe = 'c1bfa4040a0a0b8b001eeb0f3f5ee961'; //sys_id for unsubscribe

    if (input && input.action == 'UpdateRec') {
		//If we are passing in input, we toggle the record
        var updateRec = new GlideRecord('cmn_notif_message');
        updateRec.get(input.sys_id);
        if (updateRec.notification_filter == unsubscribe) {
			//if the box was unchecked, we clear the value
            updateRec.notification_filter = '';
        } else {
			//if the box was checked, we add the value
            updateRec.notification_filter = unsubscribe;
        }
		//update the record
        updateRec.update();
    }

    var gr = new GlideRecord('cmn_notif_message');
    gr.addQuery('user', currentUser);
    gr.query();
    while (gr.next()) {
        var notifObj = {};

        notifObj.message = gr.getDisplayValue('notification');
        notifObj.name = gr.getDisplayValue('user');
		//Here we add the sys_id of the record and the current state for the checkbox
        notifObj.sys_id = gr.getUniqueValue();
        notifObj.toggle = false;

        if (gr.notification_filter == unsubscribe) {
            notifObj.toggle = true;
        }

        data.list.push(notifObj);
    }

})();

I hope this helps!

If this was helpful, or correct, please be kind and mark the answer appropriately.

Michael Jones - Proud member of the GlideFast Consulting Team!

I hope this helps!
Michael D. Jones
Proud member of the GlideFast Consulting Team!

View solution in original post

4 REPLIES 4

Michael Jones -
Giga Sage

You need to track the ID of the record you want to update, create a client function to pass the data, attach it to your checkbox and then update the server code to accept input and take action. Something like this would do the trick: 

HTML: adds a way to track the record id and attaches an onclick and set the toggle based on the current state of the record. 

<div class="panel panel-default">
	<table class="table">
	  <thead>
		<tr>
		  <th scope="col">Notification Name</th>
		  <th scope="col">Device</th>
		  <th scope="col">Toggle On/Off</th>
		</tr>
	  </thead>
	  <tbody>
		<tr ng-repeat="obj in c.data.list">
		  <td>{{obj.message}}</td>
		  <td>{{obj.name}}</td>
		  <td><input id="checkbox" type="checkbox" ng-model="toggle" ng-checked="obj.toggle" ng-click="c.update(obj.sys_id)"></td>
		</tr>
	  </tbody>
	</table>
</div>

Client script: function for the onclick to take the value and pass it back to the server

api.controller=function() {

  var c = this;
	
	c.update = function(sys_id) {
		input = {};
		input.sys_id = sys_id;
		input.action = 'UpdateRec';
		
		c.server.get(input).then(function(r) {
            c.data = r.data;
        });
	};
	
};

Server Script: track the sys_id and current state for the toggle, accept input, update the record. 

(function() {
    var currentUser = gs.getUserID();
    data.list = [];

	//sys_id for the value unsubscribe, at least in my PDI
    var unsubscribe = 'c1bfa4040a0a0b8b001eeb0f3f5ee961'; //sys_id for unsubscribe

    if (input && input.action == 'UpdateRec') {
		//If we are passing in input, we toggle the record
        var updateRec = new GlideRecord('cmn_notif_message');
        updateRec.get(input.sys_id);
        if (updateRec.notification_filter == unsubscribe) {
			//if the box was unchecked, we clear the value
            updateRec.notification_filter = '';
        } else {
			//if the box was checked, we add the value
            updateRec.notification_filter = unsubscribe;
        }
		//update the record
        updateRec.update();
    }

    var gr = new GlideRecord('cmn_notif_message');
    gr.addQuery('user', currentUser);
    gr.query();
    while (gr.next()) {
        var notifObj = {};

        notifObj.message = gr.getDisplayValue('notification');
        notifObj.name = gr.getDisplayValue('user');
		//Here we add the sys_id of the record and the current state for the checkbox
        notifObj.sys_id = gr.getUniqueValue();
        notifObj.toggle = false;

        if (gr.notification_filter == unsubscribe) {
            notifObj.toggle = true;
        }

        data.list.push(notifObj);
    }

})();

I hope this helps!

If this was helpful, or correct, please be kind and mark the answer appropriately.

Michael Jones - Proud member of the GlideFast Consulting Team!

I hope this helps!
Michael D. Jones
Proud member of the GlideFast Consulting Team!

@Michael Jones - GlideFast - Thanks for your response! This is exactly what I needed!

Can I take it a step further? I am realizing that the records on the cmn_notif_message table only get created if the user is turning on/off notifications. Once the change has been registered, a new record is created on the cmn_notif_message. I will have to do a little bit of rewrite to pull all the notifications from the sysevent_email_action table and then use the solution you've provided to allow notification rewrites. 

My step further task, how can I group notifications by category and allow a toggle, at the category level, to turn off all notifications by category with an expand element on the html side. The expand element should show/collapse all notifications within that category.

I can mark this question as answered and create another question for the 2nd part if you need me to.

Thanks!

@mballinger If you're amenable, it would be appreciated if you marked this as correct, given that it answered your initial ask. 

For the additional ask, what you're wanting is possible, but a bit more complicated to achieve; and not quite something I have seen in practice. I can offer some advice and help you get moving in the right direction, but it's going to take some figuring out to be sure.

A new post might get you a wider audience and possibly a quicker answer (tag me on it) but either way I'll take a look and see what I can figure out. 

Are you wanting to simply display the individual notifications under each category, are you wanting them to be able to turn off notification for the whole category and / or select individual notifications?

Keep in mind, the sysevent_email_action table contains all possible notifications configured on the instance (even those that the user might never receive) where as the cmn_notif_message table contains records that are created once a user has actually been the recipient of a notification.  I would tend to think that cmn_notif_message is your best target, with maybe an option to group those records by category, otherwise I feel your widget might be difficult to navigate.

I hope this helps!
Michael D. Jones
Proud member of the GlideFast Consulting Team!

@Michael Jones - GlideFast - Okay sounds good. I will close this one and create a new post. Yes I want the category at the top level and then nested within is the notification. Turning the category off turns off all notifications and vice versa. Notifications need to also be managed individually. 

In addition to records on the cmn_notif_message existing due to them being the recipient of a notification, one thing I did find is when a user turns a notification on/off that does not exist on the cmn_notif_message table (from the notification preferences), a new record is also being inserted.

What I was thinking is along the same lines of what you have said. I will more than likely have to reference the sysevent_email_action table and default all messages to true. Then, when a user turns on/off a notification using the new widget, it gets registered to the cmn_notif_message table.