Add to Visual Task Board – Any record (List choice) (multi-card)

In previous articles, I explored the possibility of adding any record to a Visual Task Board from a form and from a list.

Where do we go from here?

What about selecting multiple records from a list and adding a card for each one of them?

The idea

We can use Personal tasks [vtb_task] as an interface between the VTB Card [vtb_card] and the actual record.

Instead of:

VTB Card [vtb_card] → Target record [task]

We can have:

VTB Card [vtb_card] → Personal Task [vtb_task] → Target record [any record in the system]

The code

How do we do that?

With a single UI Action and relying on the out of the box functionality.

Create a new Global UI action (easier if you just copy the OOTB one “Add to Visual Task Board”).

Name: Add to VTB (non-task) (multi-card)

Type: List choice

Action name: add_to_vtb_list_choice_non_task_multi


Code language: JavaScript (javascript)


Code language: JavaScript (javascript)


function openAddToBoardDialogListMultiCard() {

  var tableName = g_list.getTableName();
  var listId = g_list.listID;
  var list = GlideList2.get(listId);
  var checked = list.getChecked();

  if (!checked)

  var selectedIds = checked.split(',');
  var vtbIds = [];
  for (var i = 0; i < selectedIds.length; i++) {
    var currentID = selectedIds[i];
    var grVTB = new GlideRecord('vtb_task');
    var shortDescription = g_list.getCell(currentID, 'short_description') || g_list.getCell(currentID, 'name') || g_list.getCell(currentID, 'number');
    shortDescription = shortDescription ? shortDescription.innerText : 'No short description defined';
    grVTB.short_description = shortDescription;
    grVTB.description = shortDescription;

    var taskSysID = grVTB.insert();

    var grVTBComment = new GlideRecord('sys_journal_field'); = 'vtb_task';
    grVTBComment.element = 'comments';
    grVTBComment.element_id = taskSysID;
    grVTBComment.value = '[code]<a href="' + tableName + '.do?sys_id=' + currentID + '" target="_blank">' + shortDescription + '</a>[/code]';

  var url = new GlideURL("$");
  url.addParam("sysparm_nostack", "yes");
  url.addParam("sysparm_record_list", vtbIds);
  url.addParam("sysparm_table_name", 'vtb_task');

  //The code below is exactly the same that you can find in the OOTB "Add to Visual Task Board" UI Action
  var o = new GlideOverlay({
    title: getMessage("Select a Visual Task board"),
    iframe: url.getURL(),
    allowOverflowX: true,
    height: 1000,
    width: 2000,
    messages: "",
    onAfterLoad: function() {
    onBeforeLoad: function() {
      this.glideBoxCallerElement =;
    onAfterClose: function() {

  o.setPreference("sysparm_table_name", tableName);

  uncheckSelected(listId, checked);

function displayMessageStashListChoice() {

  if (!this.getData("messages"))


  var m = this.getData("messages");
  if ( {
    for (var i = 0; i <; i++) {
      var msg =[i];
      if (msg)
        addFormMessage(msg, "info", 0);

  if (m.messages.error) {
    for (var i = 0; i < m.messages.error.length; i++) {
      var msg = m.messages.error[i];
      if (msg)
        addFormMessage(msg, "error", 0);

function addFormMessage(msg, type, id) {
    msg: msg,
    type: type,
    id: id
  var scrollDiv = getFormContentParent();
  scrollDiv.scrollTop = 0;

function uncheckSelected(listId, checked) {
  var checkedIds = checked.split(',');
  for (var i = 0; i < checkedIds.length; i++)
    $('check_' + listId + '_' + checkedIds[i]).checked = false;
  $("allcheck_" + listId).checked = false;

Code language: JavaScript (javascript)


Now, we can add multiple records to a board simultaneously.

Why don’t we use all our new “Add to VTB (non-task)” UI Actions to test this feature?