Getting an HTML Input date field to display a date from a record (service portal widget)

Wayne Richmond
Tera Guru

I recently downloaded the 'My Delegates Widget' from https://snhackery.com/ and was having a go at modifying it so I can add the Start and End dates to the widget. I suceeded in getting the date fields to show and even saving the information entered. However, I can't get the fields to display the data once saved. I don't know the code well enough to understand what's acheviable. Hopefully someone can help.

This is me adding a new record:

find_real_file.png The data saved in the back-end:

find_real_file.png

The widget when I revisit the page:

find_real_file.png

If I change the input type to 'text', I can see the data is there, so I reckon I need to do something clever to get the data showing in the date input type:

find_real_file.png

Here's the code from the widget:

HTML:

<snh-panel title="'${My Delegates}'" class="panel panel-primary">
  <div style="width: 100%; padding: 5px 50px;">
    <table class="table table-hover table-condensed">
      <thead>
        <tr>
          <th style="text-align: center;">Delegate</th>
          <th style="text-align: center;">Approvals</th>
          <th style="text-align: center;">Assignments</th>
          <th style="text-align: center;">CC on Notifications</th>
          <th style="text-align: center;">Start Date</th>
          <th style="text-align: center;">End Date</th>
          <th style="text-align: center;">Remove</th>
        </tr>
      </thead>
      <tbody>
        <tr ng-repeat="item in c.data.listItems track by item.id | orderBy: 'delegate'" ng-hide="item.removed">
          <td data-th="Delegate">
            <sn-avatar class="avatar-small-medium" primary="item.id" show-presence="true"/>
            &nbsp;
            <!--<a href="?id=user_profile&table=sys_user&sys_id={{item.id}}" title="{{item.delegate}}">{{item.delegate}}</a>-->
          </td>
          <td data-th="Approvals" style="text-align: center;"><input type="checkbox" ng-model="item.approvals"/></td>
          <td data-th="Assignments" style="text-align: center;"><input type="checkbox" ng-model="item.assignments"/></td>
          <td data-th="CC on Notifications" style="text-align: center;"><input type="checkbox" ng-model="item.notifications"/></td>
          <td data-th="Start Date" style="text-align: center;"><input type="date" ng-model="item.starts"/></td>
          <td data-th="End Date" style="text-align: center;"><input type="date" ng-model="item.ends"/></td>
          <td data-th="Remove" style="text-align: center;"><img src="/images/delete_row.gif" ng-click="removePerson($index)" alt="Click here to remove this person as a delegate" title="Click here to remove this person from the list" style="cursor: pointer;"/></td>
        </tr>
      </tbody>
    </table>
    <p>To add a delegate to the list, select a person from below:</p>
    <sn-record-picker id="snrp" field="data.personToAdd" ng-change="addSelected()" table="'sys_user'" display-field="'name'" display-fields="'title,department,location,email'" value-field="'sys_id'" search-fields="'name'" page-size="20"></sn-record-picker>
    <br/>
    <p>To remove a delegate from the list, click on the Remove icon.</p>
  </div>

  <div style="width: 100%; padding: 5px 50px; text-align: center;">
    <button ng-click="saveDelegates()" class="btn btn-primary ng-binding ng-scope" role="button" title="Click here to save your changes">Save</button>
    &nbsp;
    <button ng-click="returnToProfile()" class="btn ng-binding ng-scope" role="button" title="Click here to cancel your changes">Cancel</button>
  </div>

  <div style="width: 100%; padding: 5px 50px;" ng-show="data.list2Items.length>0">
    <b>I am a Delegate for:</b>
    <div ng-repeat="item in c.data.list2Items track by item.id | orderBy: 'user'" style="padding: 5px;">
      <sn-avatar class="avatar-small-medium" primary="item.id" show-presence="true"/>
      &nbsp;
      <!--<a href="?id=user_profile&table=sys_user&sys_id={{item.id}}" title="{{item.user}}">{{item.user}}</a>-->
      for {{item.delegations}}
      <span ng-show="item.ends"> until {{item.ends}}</span>
    </div>
  </div>

</snh-panel>

Server Script:

(function() {
	data.userID = gs.getUser().getID();
	data.listItems = data.listItems || fetchList();
	data.list2Items = data.list2Items || fetchList2();
	if (input) {
		data.listItems = input.listItems || fetchList();
		if (input.personToAdd && input.personToAdd.value > '') {
			addPersonToList(input.personToAdd.value);
		}
		if (input.button == 'save') {
			saveList();
		}
	}

	function fetchList() {
		var gdt = new GlideDateTime();
		var list = [];
		var delegateGR = new GlideRecord('sys_user_delegate');
		delegateGR.addQuery('user', data.userID);
		delegateGR.orderBy('delegate.name');
		delegateGR.query();
		while (delegateGR.next()) {
			var thisDelegate = {};
			thisDelegate.sys_id = delegateGR.getValue('sys_id');
			thisDelegate.id = delegateGR.getValue('delegate');
			thisDelegate.delegate = delegateGR.getDisplayValue('delegate');
			thisDelegate.approvals = (delegateGR.getValue('approvals') == 1);
			thisDelegate.assignments = (delegateGR.getValue('assignments') == 1);
			thisDelegate.notifications = (delegateGR.getValue('notifications') == 1);
			thisDelegate.starts = delegateGR.getDisplayValue('starts');
			thisDelegate.ends = delegateGR.getDisplayValue('ends');
			list.push(thisDelegate);
		}
		return list;
	}

	function fetchList2() {
		var list = [];
		var today = new Date();
		var delegationGR = new GlideRecord('sys_user_delegate');
		delegationGR.addQuery('delegate', data.userID);
		delegationGR.orderBy('user.name');
		delegationGR.query();
		while (delegationGR.next()) {
			var stillActive = true;
			var endDate = '';
			if (delegationGR.getValue('ends')) {
				endDate = new GlideDate();
				endDate.setValue(delegationGR.getValue('ends'));
				endDate = endDate.getByFormat('dd/MM/yyyy');
				if (today.after(new Date(endDate))) {
					stillActive = false;
				} else {
					if (new Date(endDate).getFullYear() == 2100) {
						endDate = '';
					}
				}
			}
			if (stillActive) {
				var thisDelegation = {};
				var delegations = [];
				if (delegationGR.getValue('approvals') == 1) {
					delegations.push('Approvals');
				}
				if (delegationGR.getValue('assignments') == 1) {
					delegations.push('Assignments');
				}
				if (delegationGR.getValue('notifications') == 1) {
					delegations.push('CC on Notifications');
				}
				if (delegations.length > 0) {
					thisDelegation.sys_id = delegationGR.getValue('sys_id');
					thisDelegation.id = delegationGR.getValue('user');
					thisDelegation.user = delegationGR.getDisplayValue('user');
					thisDelegation.ends = endDate;
					thisDelegation.delegations = '';
					var separator = '';
					for (var i=0; i<delegations.length; i++) {
						thisDelegation.delegations += separator;
						thisDelegation.delegations += delegations[i];
						if (delegations.length > 2) {
							separator = ', ';
							if (i == (delegations.length - 2)) {
								separator = ', and ';
							}
						} else {
							separator = ' and ';
						}
					}
					list.push(thisDelegation);
				}
			}
		}
		return list;
	}

	function saveList() {
		for (var i=0; i<data.listItems.length; i++) {
			var thisDelegate = data.listItems[i];
			if (thisDelegate.removed) {
				if (thisDelegate.sys_id != 'new') {
					var gr = new GlideRecord('sys_user_delegate');
					gr.get(thisDelegate.sys_id);
					gr.deleteRecord();
				}
			} else {
				var delegateGR = new GlideRecord('sys_user_delegate');
				if (thisDelegate.sys_id != 'new') {
					delegateGR.get(thisDelegate.sys_id);
				} else {
					delegateGR.initialize();
					delegateGR.user = data.userID;
					delegateGR.delegate = thisDelegate.id;
					delegateGR.starts = thisDelegate.starts;
					delegateGR.ends = thisDelegate.ends;
				}
				delegateGR.approvals = thisDelegate.approvals;
				delegateGR.assignments = thisDelegate.assignments;
				delegateGR.notifications = thisDelegate.notifications;
				delegateGR.update();
			}
		}
		gs.addInfoMessage('Your Delegate information has been updated.');
	}

    function addPersonToList(selected) {
		var existing = -1;
		for (var i=0; i<data.listItems.length && existing == -1; i++) {
			if (data.listItems[i].id == selected) {
				existing = i;
			}
		}
		if (existing == -1) {
			var thisDelegate = {};
			thisDelegate.sys_id = 'new';
			thisDelegate.id = selected;
			var userGR = new GlideRecord('sys_user');
			userGR.get(selected);
			thisDelegate.delegate = userGR.getDisplayValue('name');
			thisDelegate.approvals = true;
			thisDelegate.assignments = true;
			thisDelegate.notifications = true;
			thisDelegate.starts = true;
			thisDelegate.ends = true;
			data.listItems.push(thisDelegate);
		} else {
			data.listItems[existing].removed = false;
		}
		input.personToAdd = {};
	}
})();

Client controller:

function MyDelegates($scope, $window) {
	var c = this;

	$scope.addSelected = function() {
		$scope.server.update().then(function(response) {
			$('#snrp').select2("val","");
		});
	};

	$scope.removePerson = function(i) {
		c.data.listItems[i].removed = true;
	};

	$scope.saveDelegates = function() {
		c.data.button = 'save';
		$scope.server.update().then(function(response) {
			reloadPage();
		});
	};

	$scope.returnToProfile = function() {
		reloadPage();
	};

	function reloadPage() {
		$window.location.reload();
	}
}

 

1 ACCEPTED SOLUTION

Taranjeet Singh
Giga Expert

Hi @Wayne Richmond ,

 

You can use <sn-date-picker> for this:

Replace '<input type="date" ng-model="item.starts"/>' with

<sp-date-picker  field="item.starts" ng-model="item.starts" sn-change="" sn-include-time="true"/>

 

and 

Replace '<input type="date" ng-model="item.ends"/>' with

<sp-date-picker  field="item.ends" ng-model="item.ends" sn-change="" sn-include-time="true"/>

 

Taranjeet 

Please mark reply as Helpful/Correct, if applicable. Thanks!

View solution in original post

5 REPLIES 5

Taranjeet Singh
Giga Expert

Hi @Wayne Richmond ,

 

You can use <sn-date-picker> for this:

Replace '<input type="date" ng-model="item.starts"/>' with

<sp-date-picker  field="item.starts" ng-model="item.starts" sn-change="" sn-include-time="true"/>

 

and 

Replace '<input type="date" ng-model="item.ends"/>' with

<sp-date-picker  field="item.ends" ng-model="item.ends" sn-change="" sn-include-time="true"/>

 

Taranjeet 

Please mark reply as Helpful/Correct, if applicable. Thanks!

Excellent! Thanks @Taranjeet Singh! Is there a list of Service Portal fields that can be used, rather than standard input fields? I'd been keen to review them. I couldn't find anything on the dev portal but I didn't really know what to search for to be honest.

Here's the working widget:

find_real_file.png

Nice enhancement! I like it!!

Thanks! I appreciate you sharing the widget in the first place.

I've parked this for the time being as I get intermittent results where I select a user to delegate to, but it doesn't get added to the form on the portal. However, the record is created on the backend. I can't replicate it now so maybe my tinkering has fixed it. 

Also, I want to hide delegations that have expired. Looking at the code, I thought it did this already, but that isn't the case. I've considered running a daily scheduled job to delete delegation records that have expired anyway, just to keep things tidy.

Thanks again! I love stumbling across little widgets and apps like this. I wish there were a better resource for them.

All the best