Interacting with Service Catalog Variable Widgets

Nick78
Tera Contributor

I have a catalog item with a Custom Variable. this custom variable is configured to display a widget on the Catalog Item to collect user information. This widget populates data onLoad of the catalog item and displays the data of users who report to the logged in user.

 

I've been tasked with updating the behavior of the widget. We would like delegates to be able to use the form, when the typical manager is unable to complete it. The end user should select the proper delegate via a new field on the form and this field should then pass the value to the Wiget, updating it with user information of the users who report to the selected delegate. In other words, if my manager sets me as a delegate. I should be able to open the form. select my manager as the delegating authority, and the widget would load user information of my managers direct reports. 

 

 

I'm struggling with how to pass a variable value in an onChange format to the server script on the widget. Is this an achievable ask? Do I need a GlideAjax script to achieve this? The server script is as follow's. I was hoping this would be achievable with a simple if statement, looking for a delegate, then pass the value of the delegate selected on the form. 

 

(function() {
    /* populate the 'data' object */
    /* e.g., data.table = $sp.getValue('table'); */
    if (!input) {
 
        var getUsers = new GlideRecord('sys_user');
        // getUsers.addEncodedQuery('managerDYNAMIC90d1921e5f510100a9ad2572f2b477fe^active=true^employee_number=NULL');
        getUsers.addQuery('manager', gs.getUserID());
        getUsers.addActiveQuery();
getUsers.addEncodedQuery('sourceLIKE-Vendor');
      //  getUsers.addEncodedQuery('employee_number=NULL');
        getUsers.query();
 
        var usersArray = [];
        var i = 1;
        while (getUsers.next()) {
            var userObj = {};
            userObj.id = i;
            userObj.user_id = getUsers.user_name.toString();
            userObj.user_name = getUsers.name.toString();
            userObj.company = getUsers.company.name.toString();
            userObj.facility = getUsers.location.name.toString();
            userObj.manager = getUsers.manager.name.toString();
            userObj.domain_account_expiration = getUsers.u_account_expiration_date.toString();
            userObj.isrefreshed = false;
            userObj.isdeleted = false;
 
            usersArray.push(userObj);
            i++;
        }
        data.users = usersArray;
    }
})();
6 REPLIES 6

I'm not sure if you've got a solution or not, but if you're still troubleshooting my first piece of advice would be to put some logging in place to make sure your server script function is calling. No point in trying to go further if you can't call it.

 


@Nick78 wrote:

I suspect the problem I'm running into now is on the server side in translating the 'manager' into the correct format.


It looks like you're creating an object with attributes, so that can happen. As with the above, I'd like spit out the object into a console.log to show it's being created and returned to the front-end fine. What are you looking to do with the object in the front-end?

 


@Nick78 wrote:

But do have a question on your client controller example. In the following line, does "proposed_date_first" reference back to any value on a form or elsewhere?

c.data.proposed_date_first = response.data.prettied_date;

In my case I am returning the "pretty" date back to the client script. I have a spot in the Body HTML Template where I display that value, so it updates whenever the client script updates:

I am available to discuss this matter with you on: {{c.data.proposed_date_first}} at {{c.data.proposed_time_first}}{{c.data.proposed_date_time_second_third}} (dates and times in MST).

What I wanted to do was have the date in a nice format rather than "03/02/2025" which could result in confusion since 03 and 02 are valid for both months and days. I have to format dates multiple times and using GlideDate worked perfect (but needed to be server side).

 

 

What I assume you want to do is:

a) Validate the server function is being called and creating the object fine with the data passed to it (gs.info is a lazy but easy way to do this).

b) Validate the client script is getting the object (console.log is a lazy but easy way to do this).

c) Do your "work" with the object.

 

Once (a) and (b) are running, let me know what help you need with (c) and we can figure out how to make the object do what you are intending. We just need to make sure the data works it's way back to the client controller that you need. From your code and description this all seems like it will be straight forward as you do this already, but you need a way to refresh with the delegate vs the logged in user.

_ukasz Rybicki
Giga Guru

Watch the catalog variable for changes, call c.server.get() with the new delegate’s sys_id, and on the server filter sys_user records by manager = input.delegate to reload the direct reports list.

  1. Add a Delegate variable

    • In your Catalog Item, create a Reference variable (u_delegate) pointing to sys_user.

  2. Client Controller

    api.controller = function($scope) {
      var c = this;
      var g_form = $scope.page.g_form;
      // Watch for delegate changes
      $scope.$watch(function() {
        return g_form.getValue('u_delegate');
      }, function(delegateId) {
        if (delegateId) {
          // Fetch reports for the selected delegate
          c.server.get({ action: 'get_delegate', delegate: delegateId })
           .then(function(res) {
             c.data.users = res.data.users;
           });
        }
      });
    };
  3. Server Script

    (function() {
      if (input && input.action === 'get_delegate') {
        var gr = new GlideRecord('sys_user');
        gr.addQuery('manager', input.delegate);
        gr.addActiveQuery();
        gr.query();
        data.users = [];
        while (gr.next()) {
          data.users.push({
            sys_id: gr.sys_id.toString(),
            user_name: gr.name.toString(),
            user_id: gr.user_name.toString(),
            company: gr.company.name.toString(),
            facility: gr.location.name.toString()
          });
        }
        return;
      }
      // Initial load: current user’s direct reports
      var gr0 = new GlideRecord('sys_user');
      gr0.addQuery('manager', gs.getUserID());
      gr0.addActiveQuery();
      gr0.query();
      data.users = [];
      while (gr0.next()) {
        data.users.push({
          sys_id: gr0.sys_id.toString(),
          user_name: gr0.name.toString()
        });
      }
    })();
  4. Test

    • Open the catalog item.

    • Pick a delegate in the Delegat field.

    • The widget’s list should instantly refresh to show that delegate’s direct reports.