Table Component: Custom Mass Actions

The Table component provides a baseline set of mass actions “out of the box” that meet the most common needs for inline editing. Using snippets, you can expand on this baseline to add customized and advanced tools for your end users.

Mass Action Snippet Reference

A mass action snippet is run when an end user selects (“checks”) one or more rows within the table and then clicks on a Mass Action from the Mass Action dropdown list.

A mass action snippet receives a single argument with the following properties:

  • arguments[0].action ($( XML Element )): The XML node which defines this action.
  • arguments[0].list (skuid.ui.List): The List to which the Mass Action should be applied.
  • arguments[0].model (skuid.model.Model): The Model from which the List’s data is derived.

Though one or more rows must be selected in order to see (and thus execute) a Mass Action, the Mass Action itself is not restricted to working with rows that have been selected. If you noticed, the snippet does not receive a “selected items” argument. Even so, your Mass Actions should generally only operate on selected items, as any other behavior would violate UX norms and may be confusing and frustrating for users.

To get an array of skuid.ui.Item objects representing the selected rows, use the getSelectedItems() function of the List:

1
var selectedItems = arguments[0].list.getSelectedItems();

Example 1: One Action Per Row

In this example, we’ll read in the address data for each selected Lead and provide a Mass Action which opens each address in a new Google Maps window. To make the example more compelling, we’ll also read in the address of the currently logged-in user and create directions from the user to the Lead.

To begin, create a new Skuid page with the following properties:

  • Page Name: SkuidSample_CustomMassAction
  • Type: Desktop
  • Template: Object list / tab page
  • Select Primary Object: Lead

Add the following fields to the Lead Model:

  • Street
  • City
  • State
  • PostalCode
  • Country

In order to see that the Mass Action is working, add a single Template component column to the Table component with the address data in a reasonable format. It is not necessary to actually render the fields used by the Mass Action, but it is a handy way to make sure that the correct address is loaded. Add a Template component to the table with the following Template code:

1
2
3
{{{Street}}}
{{{City}}}, {{{State}}} {{{PostalCode}}}
{{{Country}}}

Set the Template’s Label property to “Address.”

Now, in order to get the address of the current end user, we need to build a second Model with the following properties:

  • Model Id: CurrentUser
  • SObject Type: User

Then add a new condition to the Model with the following properties:

  • Field: Id
  • Operator: =
  • Value - Content: UserInfo of page viewer
  • Value - UserInfo Property: User Id
  • State - Condition State: Always On

Add the following fields to the Model:

  • Street
  • City
  • State/Province
  • Zip/Postal Code
  • Country

Now that the Models are defined, it is time to create the Mass Action. Select the Table component and click “Add Features” then “Add Mass Action”:

This will add a new Mass Action labeled “New Custom Mass Action” (this is a default value). Click the Mass Action and change the following properties:

  • Action Type: Custom
  • Action Label: Get Directions
  • Action Icon: ui-silk-map-go
  • Snippet Name: SkuidSample.GetDirectionsMassAction

Open the “Resources” tab and create a new Javascript resource with the following properties:

  • Resource Location: In-Line (Snippet)
  • Snippet Name: SkuidSample.GetDirectionsMassAction

In the code body, start by assigning the snippet arguments to variables:

1
2
3
4
5
var $ = skuid.$,
    action = arguments[0].action,
    list = arguments[0].list,
    model = arguments[0].model,
    selectedItems = list.getSelectedItems();

Next, define a function which is able to extract the appropriate fields from a row and build an address string appropriate for Google.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
function buildAddress( row )
{
    // Assemble the address from most specific to least
    var address =
        ( row.Street ? ', ' + row.Street : '' ) +
        ( row.City ? ', ' + row.City : '' ) +
        ( row.State ? ', ' + row.State : '' ) +
        ( row.PostalCode ? ', ' + row.PostalCode : '' ) +
        ( row.Country ? ', ' + row.Country : '' );

// If the address is not defined, try the company name instead
if ( !address )
    return row.Company;

// If the address is defined, then return it (after removing the leading ", ")
return address.slice( 2 );
}

The “CurrentUser” Model will automatically pull in the address fields for the currently logged in user. To access it from JavaScript, call the skuid.model.getModel() function like so:

1
var currentUserModel = skuid.model.getModel( 'CurrentUser' );

This will return a skuid.model.Model(), from which the query results can be retrieved. In this example, only one row is expected (since the query is based on the row Id field). The getFirstRow() function provides a useful shortcut to get at this single row:

1
var userRow = currentUserModel.getFirstRow();

Finally, all that is left is to iterate over the selected Items and, using the buildAddress() function, build a URL for Google Maps and open it in a new window:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
var currentUserModel = skuid.model.getModel( 'CurrentUser' ),
    userRow = currentUserModel.getFirstRow(),
    userAddress = buildAddress( userRow );

$.each( selectedItems,
    function( i, item )
    {
        var leadAddress = buildAddress( item.row );
        // Build a URL to get direction FROM userAddress TO leadAddress
        var mapsUrl = 'https://www.google.com/maps/dir/' + encodeURI( userAddress ) + '/' + encodeURI( leadAddress );
        window.open( mapsUrl );
    });

Save the changes and open a preview of the page. Select a couple records and then choose “Get Directions” from the Table’s Mass Actions dropdown. You should see something like this:

Clicking the custom mass action once will open a browser window or tab for each selected row's address.

The code iterates over each selected item and opens Google Maps in a new browser window with directions from the current user’s address to the Lead’s address. (The exact results depend on your browser, which among other things, may open the windows as new tabs.)

Example 2: One Action for All Rows

This example will be nearly identical to Example 1 except that rather than performing an action for each selected item, the data from all the items will be collated and a single action will be performed for all selected rows. Specifically, we’ll open Google Maps in just one window and include all selected destinations in the resulting directions.

To accomplish this, create a variable to hold the collated data, named url:

1
var mapsUrl = 'https://www.google.com/maps/dir/' + encodeURI( userAddress );

Iterate over the collection of selected Items, just as before, except this time append the address string to the mapsUrl variable rather than immediately opening the window:

1
2
3
4
5
6
$.each( selectedItems,
function( i, item )
{
    var leadAddress = buildAddress( item.row );
    mapsUrl += '/' + encodeURI( leadAddress );
});

When all of the selected items have been appended to url variable, then open a window (just one):

1
window.open( mapsUrl );

And the result:

Each selected row's address will be added as a stop inside one set of directions, and a new browser window or tab will open to display those directions.

Example 3: Updating Data via Mass Action

The examples so far have only demonstrated reading data from the List and performing actions based on it. Using the Skuid API, however, you can alsoupdate data.

In this example, we’ll automate the process of updating the Status of a Lead to “Qualified.” Normally, the end user would need to bring each row into “edit” mode (for example, by clicking the edit button), pick a value from the picklist, then commit the changes by clicking the “save” button. We’ll introduce a new custom Mass Action that will perform all of these steps with a single click for all selected rows.

First, include the Status field in the Lead Model, then add the Status field to the table component.

Next, create a new Mass Action with the following properties:

  • Action Type: Custom
  • Action Label: Mark All as Qualified
  • Action Icon: ui-silk-user-go
  • Snippet Name: SkuidSample.QualifySelectedMassAction

The snippet itself will contain relatively little code. Start by defining the argument variables:

1
2
3
4
5
var $ = skuid.$,
    action = arguments[0].action,
    list = arguments[0].list,
    model = arguments[0].model,
    selectedItems = list.getSelectedItems();

It would be tempting at this point to iterate over the selectedItems and simply call updateRow() for each of them. While this would certainly get the job done, it’s extremely inefficient.

It may take a few extra lines of code, but compiling a list of needed changes and then requesting them all at once via updateRows() will yield significantly better performance and scalability.

To compile the list of needed changes, start by creating the rowsToUpdate variable. This will contain all the changes that will be sent to the Lead Model.

1
var rowsToUpdate = {};

Next, iterate over the selected items. Add the selected row’s Id to the rowsToUpdate variable and define the new value, “Qualified,” for the Status field:

1
2
3
4
5
6
$.each( selectedItems,
    function( i, item )
    {
        var row = item.row;
        rowsToUpdate[ row.Id ] = { Status: 'Qualified' };
    });

Use the Model’s updateRows() function to request all row updates at once:

1
model.updateRows( rowsToUpdate );

To commit the changes, call the Model’s save() function.

1
model.save();

Note

Under normal circumstances it is best to let the user of your application save values explicitly. This gives the user a chance to cancel a mistaken click, etc, before the value is committed to the database.**

Clicking the “Mark as Qualified” button on the table will change the Status and commit the changes to the database in a single step:

Updating the status for multiple rows can be accomplished using this one custom mass action. Note that, as this custom mass action will automatically save the value changes, your save and cancel buttons will not be selected; the data is already committed.

After clicking, you may see a momentary flicker of the Save and Cancel buttons as the change notification propagates through the Skuid system, immediately followed by a command to commit the Model (thus disabling the Save and Cancel buttons).