Skuid and JavaScript

JavaScript is the key to developer greatness with Skuid. Our robust JavaScript API provides simple functions for performing client-side CRUD operations on any data object from a connected data source, as well as saving this data to your data sources’ servers. And with snippets and custom components, you can utilize JavaScript for programmatic control and extension of your Skuid implementation.

In this article, we will cover the basics of navigating and interacting with data in Skuid using JavaScript. However, the intricacies of the language are beyond the scope of this documentation. If you are JavaScript beginner, or if you just need a refresher course, please refer to your favorite JavaScript resource. MDN’s JavaScript portal is just one of many great options.

How Skuid Accesses Your JavaScript

So, how does Skuid access your JavaScript? In the same way it accesses other custom code:

  • In-line resources
  • External resources
  • Static resources

Get familiar with the console

In addition to these resource types, you can also utilize JavaScript (and Skuid’s JavaScript API) through your browser’s console. The console is an essential tool in leveraging Skuid’s JavaScript API. Make sure you are familiar with the console in your browser of choice:

Note

Pull up your browser’s console and type skuid. Now press Enter on your keyboard. You’ll see the “skuid” JavaScript object—a powerful artifact containing all of the objects and functions to make you a Skuid development superhero. Depending on your browser, you’ll also notice that you can click through to those objects and functions within it.

Guess what? You’ve just had your first experience with…

The Skuid JavaScript API

Within each Skuid page—both in the App Composer and at runtime—there is a JavaScript object called skuid which houses all of the functions, data, and objects of the page. While JavaScript can be used for a variety of purposes (such as DOM manipulation), in Skuid you’ll mostly work with Skuid’s JavaScript API reference through that skuid object.

The Skuid JavaScript API can do all of the basic, declarative actions of Skuid, including:

  • Query and update data from your data sources through models
  • Save and cancel data changes
  • Set and activate model conditions

But it’s also used to make the magic happen. Once you’ve mastered the JavaScript API, you can use it to:

  • Easily debug issues—even declarative ones—on your Skuid pages
  • Write JavaScript snippets for page-specific use cases or custom field renderers
  • Build custom components that read, display, and write data in almost any way you can imagine.

Strict Mode

Skuid enforces strict mode on its own code. Strict mode will be enforced on custom code within pages deployed through the Skuid Page Lightning component in orgs that have LockerService enabled. Because of this, any custom code used in these pages that does not follow strict mode standards will break until it is revised.

We recommend users consistently follow strict mode standards throughout all of their custom code, regardless of deployment context.

Best Practices

Favor the Action Framework over writing JavaScript

While it may seem counter-intuitive as a developer, you should always check to see if the Action Framework can do what you need before writing any JavaScript. The Action Framework has the advantage of being written by the same people who wrote our API, and it has been tested across thousands of orgs in every possible configuration. It’s incredibly robust, and it is constantly being updated and refined to work as efficiently as possible.

If you need to run straightforward sequences of actions, such as creating records, querying and emptying models, activating conditions, or even actions that require heavy manipulation of the UI (like messages and popups), then the Action Framework will suit your purposes just fine. Skuid’s App Composer can be used to create these types of user experiences much more quickly than writing code.

In fact, as the Action Framework’s capabilities expand, it’s a best practice to revisit existing JavaScript code snippets and replace them with Action Framework actions whenever possible.

So when should I use JavaScript instead of the Action Framework?

Use JavaScript for more complex actions or conditional branching of the action script, or when you want the sequence to be triggered in a scenario or component where the Action Framework isn’t available. If you have ideas for a component that takes your user experience further, don’t hesitate to use JavaScript to create a custom component.

Use variables to access objects whenever possible

Skuid’s API will return objects and data you’ll want to work with as the result of a function. Functions can return JavaScript objects that represent models, components, rows, field data, and other modifiable data:

1
2
3
skuid.model.getModel('Opportunity') // Accessing a model //
skuid.component.getById('sk-1IioRB-76') // Accessing a component //
skuid.model.getModel('Opportunity').getFirstRow().Name // Accessing the "Name" field from the first row of the Opportunity model//

Clearly, this can get convoluted very quickly. So for both readability and convenience, use variables for Skuid functions:

1
2
3
var Opps = skuid.model.getModel('Opportunity') // Accessing a model //
Opps.getFirstRow().Name // Accessing the "Name" field from the first row of the Opportunity model, but easier!//
var bc = skuid.builder.core //For cleanliness in Skuid custom component builders

Do Not Use jQuery’s Ready Event to Determine If a Page is Loaded

The jQuery ready event may not accurately reflect when a Skuid page is loaded. While snippets may still run, they may not consistently have access to some Skuid data, such as client-side model metadata.

To reliably trigger snippets when all elements are loaded, utilize Skuid’s pageload event.

If your snippet uses either of the below:

$(document).ready(function() {

// Or the following, which is shorthand for the above:

$(function(){

Use the following instead:

$(document.body).one('pageload',function() { // Will fire after Skuid is finished fully loading the page

If your Skuid version supports it, strongly consider using event-triggered action sequences. Creating a sequence triggered by the Skuid Page: Rendered event, with the Run A Skuid Javascript Snippet action activating a snippet will accomplish the same effect in a less error-prone, more future-proof manner.

Warning

In contexts where there may be multiple Skuid pages loading simultaneously—Page Includes, Salesforce Lightning apps—the above function would trigger based on whichever page loads first, which may not be the the page containing the snippet. Strongly consider using event-triggered sequences instead.

JQuery and Skuid

Skuid includes the most up-to-date version of jQuery 3, and jQuery functions are accessible by using the skuid.$ API call. Because Skuid uses this custom namespace to avoid conflicts, you are free to load in any version of jQuery, or any other library, that you’d like to use alongside your Skuid page.

If you choose not load in any other libraries, it’s common practice to create a more standard shortcut to JQuery:

1
var $ = skuid.$;

After calling this, you have access to all jQuery functions, simply using the $. For example, you can now call $('#unique-id').hide() rather than skuid.$('#unique-id').hide()

Warning

Previous versions of Skuid included jQuery 1. If your code references jQuery 1, read the jQuery Upgrade Guide to ensure your code is properly written for jQuery 3.

Using Skuid with JavaScript: A Primer

The Skuid JavaScript API is powerful, but with that power comes complexity. The best way to overcome that complexity and illustrate some of its concepts and uses is by trying it. So let’s do that!

Create a test page

Note

To protect your data, create this test page in a personal developer org or a sandbox org .

  1. From the Skuid navbar, click Compose > New Page
  2. Enter a Page Name—any name will work.
  3. Click Next Step.
  4. As your Starting point, select Use a page template.
  5. Click Select Page Template.
  6. In the Create New Page dialog, set your Primary Object to any data object with multiple records, e.g. Account. Leave everything else at their default settings.

Note

In the examples that follow, it’s assumed you are using the Account object, with your model also named Account. If you are using a different data object, substitute the name of the object/model you used.

  1. Click Create Page.
  2. In your new page, in the properties pane, click Layout.
  3. Unclick the Show Salesforce Header and Show Salesforce sidebar checkboxes.
    • This ensures compatibility across browser consoles.
  4. Preview your newly created Skuid page.

With this Skuid page, you’ll be able to learn the basics of how to use the Skuid JavaScript API.

To ensure the page is set up correctly:

  1. In your preview, open your browser’s console
  2. Type skuid in the console. The skuid object should be returned in your console.

Some Basics

When you preview your page, you’ll see a basic table, with a list of accounts, attached to the account model. As a user this is a handy way to see the information, but how can a developer access model data programmatically? How can they update rows of data within a model programmatically? How can they control the UI to display appropriate popup messages to the user? Whether you’re writing a small snippet or a completely custom component, you’ll need to have a grasp on these basic Skuid actions.

Let’s look at how to do all that using the API.

Accessing model data

Seeing all models on a page

First, let’s see which models are on the page.

  1. Open your browser’s console.
  2. Type skuid.model.map(). Skuid will return an object that has all of your model IDs as its properties, with the model data as values of those properties.

What if—for your use case—you’d like to receive that data as an array? Then type

1
skuid.model.getModelList()

Again you’ll all of your model’s data listed, but this time as an array. You can often access the same data in a variety of ways, so choose the data type most appropriate for your use.

For example, enter the following:

1
2
modelsObject = skuid.model.map();
modelsArray = skuid.model.getModelList();

Now you’ll find that you reach your Account object in two ways:

modelsObject.Account
or
modelsArray[0]

But this isn’t the most efficient—or in the case of the array, the most accurate—way to reach a specific model’s data.

Accessing a single model’s data

If you know the ID of your model—or if your code will eventually be used as a snippet or custom component across pages—you’ll likely be using it to access or update the data of one or more models. To do that, you’ll need to access that model as a JavaScript object.

Type the following:

1
skuid.model.getModel('Account');

This function will return our model data as an skuid.model.Model object, much like the above code, but we’re reaching it in one step. Now let’s use a variable to refer to this function so everything we do moving forward is much more readable.

1
var account = skuid.model.getModel('Account');

Note

When creating variable shortcuts, undefined will often be returned by the console. This is normal, and entering your variable after defining it will return the object you created a shortcut to.

A key point to remember here is that—when using the JavaScript API—you invoke functions and then work with the data returned by those functions.

When you work declaratively, referring to models, pages, and other elements by their IDs is enough to access and modify them because they exist as unique, concrete entities that you can modify. In contrast, when working with data programmatically using the JavaScript API, you must invoke a function that then returns the element—in essence, you must first ask for an element before you can modify it. (Depending on your experience with JavaScript, you may have already run across this concept, particularly with the often-used document.getElementByID() function.)

Because of this difference in how you handle data when working programmatically, it’s best practice to use appropriate variable shortcuts for both clarity and convenience.

After declaring our shortcut variables, typing either the skuid.model.getModel('Account').id or account.id, would return the same data. As listed in the Best Practices section, using the variable shortcut is the preferable option.

Whenever you invoke skuid.model.getModel(), you can be able to browse the model object within your console. But to demonstrate how your new shortcut variable works, try entering some of the following in your browser’s console:

1
2
3
4
account.objectName //Returns the name of the data source object retrieved by the model//;
account.data //Returns all the record rows inside your model as an array of objects.//;
account.dataMap //Returns all the record rows inside your model as an object, with each row as a property.//;
account.conditions //Returns all of the model's conditions as an array of objects. //;

Interacting with your model

Now that we know how to reach our model’s data, let’s look at how we can interact with that data programmatically.

First, create a new row on your table by typing account.createRow() in your console. Simple enough, but how do we input data into our newly created row?

Updating a row

1
account.updateRow(account.getFirstRow(),{Name:'My First API Row Update!'}) //updateRow accepts two parameters: the row to update (as a JavaScript object), and the updates to make (also as a JavaScript object) //;

So let’s break down how this works:

  • the updateRow() function tells Skuid we want to update a row, so our first parameter must be that row as an object.
  • Using the getFirstRow() function as the first parameter tells Skuid to look for the row at the top of that model’s data and return it as an object that the updateRow() function can recognize.
  • The second parameter is a JavaScript object with properties that correlate to
    • The data field ID, “Name”
    • The value to update that field to, “My First API Update!’

You could also:

  • Use an explicit object literal for your row ID paramater, e.g. {Id:”"0012603000X4aYYAAZ"”}.

  • Update more than one field in a row at a time, e.g. {Name:”aName”,BillingCity:”aCity”,CustomField__c:”A custom value”}.

  • Create and update your row in one line:
    1
    account.updateRow(account.createRow(),{Name:'Created in one line'});
    

Since our table is currently in in-line edit mode, let’s cancel all of our changes to the model so far by using the cancel() function.

1
account.cancel();

Canceling specific rows and saving

Now, let’s create two rows that are stored within variables so we can have more granular control over what we do and do not cancel. Copy and paste the following in your console:

1
2
3
4
var workingRow = account.createRow() //The newly created row returned by this function will be known as "workingRow" //;
account.updateRow(workingRow,{Name:'Working Row'}) //We are now using our newly created and identified row object as our updateRow parameter // ;
var anotherRow = account.createRow() //A second created row stored in another unique variable //;
account.updateRow(anotherRow,{Name:'Another Row'}) ;

Retrieving data from a row

Now we have consistent identifiers for the rows our JavaScript has created. This can be essential when writing snippets or custom component that manipulate model data. By using these row identifiers, we can update—even using data from one row in the other—and abandon these rows easily.

First, let’s look at how we can retrieve data from a particular row:

1
anotherRow.Name;

Entering this will return the value of the Name field on our anotherRow row in our account model. As you can see, by using the functions you’ve learned thus far, along with variable shortcuts, you can easily drill down into your data as far as you’d like.

Now that we know we can access that data programmatically, let’s use it to update our workingRow’s Name field. Then we can cancel our extra row by using abandonRow().

1
2
account.updateRow(workingRow,{Name:anotherRow.Name}) //Updating the workingRow using data from a different row that is stored in a variable, as opposed to using an explicit string //;
account.abandonRow(anotherRow) //Abandoning a specific row allows us to cancel one row without destroying them all //;

And with that, in our hypothetical use case, we’ve made all the changes we want to in our data object.

Let’s save those changes with a function that may be the simplest thus far

1
account.save();

But wait! Changed your mind? Don’t want that garbage row you just saved in your data? Easy fix: delete it instead.

1
2
3
workingRow //First, enter this to see that the row—even after being saved—is still stored within its variable. The row's Id field was updated when it was saved, but that field is also updated within your object as well. //;
account.deleteRow(workingRow) //This function will mark the row for deletion, but it won't be deleted from your data object until you use save()//;
account.save();

Creating a popup

And with that, you’ve accomplished a few common Skuid activities entirely through JavaScript. Let’s display a celebratory message with the blockUI() function.

skuid.$.blockUI({ message: '<h1>You\\'ve used Skuid exclusively through JavaScript!</h1><h2>You\\'re on your way to becoming a pro Skuid developer</h2><h3>Also notice how you can use HTML within your blockUI message!</h3><br/>How <i>cool</i> is that?' });

Okay, so when you’re finished admiring your work, you can unblock your UI just as easily:

1
skuid.$.unblockUI()

Now, go develop!

Though the Skuid JavaScript API is far too vast to cover its intricacies in this overview, you’ve now seen how you can use some of its functions in a basic sense. You can create powerful snippets or intricate custom components using the above functions; doing so just requires that you build on the knowledge you’ve established here.