Welcome to Community Week 2025! Join us to learn, connect, and be recognized as we celebrate the spirit of Community and the power of AI. Get the details  

Watchlist in Service Portal Record Producer SOLVED

Doncho Todorov
Tera Contributor

Hello, I came across an interesting case where I had to replicate the "Watchlist" in the Service Portal on a "Record Producer." The issue was that it required the ability to add both internal and external email addresses to the "Watchlist" as it is in the backend. So, the solution I implemented involves a "Custom Variable with Label" containing a "Widget" and a hidden "Single Line Text Variable" that permanently holds the "sys_id" and emails.

Here's the HTML code for the Watchlist Widget:

 

 

<div class="container">
  <sn-record-picker
    on-change="c.onWatchListChange(picker)"
    field="picker"
    table="'sys_user'"
    multiple="true"
    display-field="'name'"
    value-field="'sys_id'"
    search-fields="'name'"
    page-size="100"
  ></sn-record-picker>

  <div class="emailContainer">
    <input
      class="form-control"
      type="email"
      id="emailInput"
      name="emailInput"
      placeholder="example@email.com"
    />
    <button class="btn btn-primary" ng-click="c.addEmailToWatchList()">
      Add Email
    </button>
  </div>
</div>

 

 


And the CSS for the Watchlist Widget, I've used two of the OOTB classes in ServiceNow and a bit of custom CSS as well:

 

 

.container {
  width: 100%;
  margin: 0 auto;
  padding: 20px;
  border: 1px solid #999;
  border-radius: 8px;
  font-size: 100%;
}
.emailContainer {
  margin-top: 20px;
  display: flex;
  justify-content: space-between;
}
.form-control {
  margin-right: 10px;
}

 

 

And the JavaScript for the client controller of the Watchlist Widget:

 

 

api.controller = function ($scope) {
  var c = this;

  c.addEmailToWatchList = function () {
    var emailInput = document.getElementById("emailInput");
    var emailRegex =
      /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(?:\.[a-zA-Z]{2,})?$/;

    if (emailInput.value && emailRegex.test(emailInput.value)) {
      var watchListValues = $scope.picker.value;
      var displayValues = $scope.picker.displayValue;

      if (watchListValues) {
        if (watchListValues.indexOf(emailInput.value) == -1) {
          displayValues += "####" + emailInput.value;
          watchListValues += "," + emailInput.value;
        }
      } else {
        displayValues = emailInput.value;
        watchListValues = emailInput.value;
      }

      $scope.picker = {
        displayValue: displayValues,
        value: watchListValues,
      };

      $scope.page.g_form.setValue("watch_list", $scope.picker.value);

      emailInput.value = "";
    }
  };

  c.onWatchListChange = function (picker) {
    $scope.page.g_form.setValue("watch_list", picker.value);
  };
};

 

 


So, when someone selects multiple people and adds an email to the Watchlist, it immediately updates the "Single Text Line variable," which is always hidden on the form, containing the "sys_id" and email addresses. This variable is mapped to "watch_list" in the backend and populates it upon form submission.
P.S - Don't forget to create your "Single Text Variable" and map to field it to the "Watchlist" in the backend. When you map the variable will automatically take the name "watch_list" or if it's a custom table make sure to put the value of your custom "Watchlist" in the Client Controller.

I'm attaching a picture of how the watchlist look below.
Hope this helps many people 🙂 !

Kind Regards,
Doncho Todorov

My LinkedIn  

1 ACCEPTED SOLUTION

skp
Tera Expert

Thank you, Doncho. Your solution is excellent and incredibly helpful.

View solution in original post

1 REPLY 1

skp
Tera Expert

Thank you, Doncho. Your solution is excellent and incredibly helpful.