As we saw in the first article in this series, the goal of the SAS Viya API Wrappers for JS is to facilitate the development of custom Web applications that can, for example, use the SAS Compute Server to populate prompts. One of the use cases is to create dynamic prompts for SAS Viya jobs. In this article, I will walk you through the steps of creating "advanced" dynamic prompts. A first example helped you mirror the capabilities that SAS provides out-of-the-box (more information). In this example, we will see how to create dynamic prompts, customize the look and feel of a selection element with checkboxes, sliders and also add business logic to force users to select multiple values before submitting the job.
The SAS Viya Wrappers for JS are designed to be used as a CDN package as well as inside a NodeJS based application via npm installation. Using a CDN, you can write the application in your favorite text editor or inside SAS Studio when creating a SAS Viya job. Using the npm installation method, you need to configure NodeJS and install the required dependencies using npm. In this article, we will cover using the CDN. A later article will explain how to use the SAS Viya API Wrappers for JS within a NodeJS based application. To use the library inside your web page, you need to import it into an HTML script tag like this one:
<script type="importmap" crossorigin="anonymous">
{
"imports": {
"sas-wrappers": "https://cdn.jsdelivr.net/npm/sas-viya-api-wrappers-js/dist/sas-viya-api-wrappers-js.js"
},
"integrity": {
"https://cdn.jsdelivr.net/npm/sas-viya-api-wrappers-js/dist/sas-viya-api-wrappers-js.js": "sha256-o5E56OSVRTSJlYXb+/M2vL+Dj2Q8o59+WsrVOBKolwU="
}
}
</script>
Note that you should update the hash key in the integrity every time the sas-viya-api-wrappers-js.js is updated. If the hash is not correct, you will see an error in your browser's developer tools. For more information about the importmap type for script, please refer to this documentation. This declaration makes the library available in the web page, and it can be referenced as sas-wrappers in other HTML script tags on the same page using an import statement like this:
<script type="module">
import { ComputeSession } from 'sas-wrappers'
const computeSession = await ComputeSession.init({baseURL: 'https://server.demo.sas.com',contextName: 'SAS Job Execution compute context'})
// Remaining code
</script>
You now have a SAS Compute Server session. This session object can then be used to call the various methods provided by the library to get a list of libraries, tables, columns, and values.
In this example, we will demonstrate how to customize the form elements of the SAS Viya job to force users to select multiple values before the Submit button is enabled. In addition, we will see how we can use checkboxes instead of the HTML select element for multiple selection. At the same time, our page will render the result of the job execution on the same page, allowing the end user to see the selection and the result on the same page.
Select any image to see a larger version.
Mobile users: To view the images, select the "Full" version at the bottom of the page.
WARNING: images are based on version 1.2.4 of the library. Starting with version 1.2.5, the method signatures have changed to pass an object instead of a list of parameters.
Let us start with the HTML Head section, where we need to import the different libraries.
As you can see, we import the CSS stylesheet from Bootstrap and the sas-viya-api-wrappers-js.js from jsDelivr CDN hosting. We also define the css for the iframe element. Using an iframe is the technique used to display the result of the job on the same page as the prompt.
The body element is then defined with the following class "container-fluid". The top of the form element contains some layout elements and, most importantly, the two hidden elements used to invoke the SAS Viya job:
If you are familiar with SAS Job Execution and building HTML forms, you may have noticed that the hidden input element for _program has been defined as the path to the job.
By default, all elements in the form are disabled. We will enable them later using the JavaScript code. This will allow us to dynamically enable/disable the element based on some business rules.
After the form element, we define the iframe element that will receive the result of the job execution.
The final HTML element is a modal that is displayed while data is being retrieved from the server. The modal displays a spinner when a call to the REST APIs is made and disappears when the UI is ready for user interaction.
That's it for the HTML code. The rest of the body element will be JavaScript code. We start with the code to start a Compute Server session:
<script type="module">
import { ComputeSession } from 'sas-wrappers'
const computeSession = await ComputeSession.init({baseURL: 'https://server.demo.sas.com', contextName:'SAS Job Execution compute context'})
// Remaining code
</script>
To determine if we can submit the form, we will do some basic validation. To store the information about the fields that have been validated, we initialize an empty array.
const validFields = []
We will add element ids to this array if they are valid, and then check the contents of the array to enable or disable the submit button.
We then have a few functions to populate the dropdown, checkbox, and range elements:
As you can see in the code above, the slider element is populated based on a specific SQL query. The query is generated on the fly based on the value of the regionSelect property. The generated code is used to call the executeCode method of the ComputeSession. The result of the code execution is then used to adjust the properties of the HTML element.
The final function is the enableSubmit function, which checks the contents of the validFields array to determine whether or not the job can be submitted:
Now that the functions are defined, we have everything we need to start implementing the business logic. To interact with the HTML elements, we will simply define variables that hold a pointer to the DOM element.
As you can see, the loader variable has a different definition. This is because we are creating a modal using the bootstrap library. Setting the background to static disables any interaction while the modal is displayed. This means that there is no way to close the modal by clicking outside of it.
Let's move on to the business logic. The first action that occurs is the populating of the regionSelect element. We will first display the loader modal and then retrieve data from the compute server. As soon as we get data, the selectRegion element is populated and the modal is closed:
We will then go on to define what happens when the user selects a region of interest:
As you can see in the code, selecting a region triggers a few actions:
Nearly the same logic applies for the typesSelect:
As you can see at the beginning of the function, we retrieve the value of the regionSelect element to create a filter and display only the types available in a specific origin.
On lines 270 through 274, we check the number of checkboxes in the typesCheckboxes element that have a state of checked. If we have more than one checked element, the typeCheckboxes element is added to the validFields array. If not, it will be removed from the array. This means that we should have at least two values selected for this element to be considered valid.
We then have two event listeners for the scope. The event listeners will display the selected value. This is not mandatory, but it informs the user of their selection.
The last bit of JavaScript is to handle form submission. By default, submitting the form will call the job and display the result in an empty page. This is not the behavior we want to implement. We want the results to appear in the iframe below the form. This is the role of this event listener.
As you can read, we prevent the default behavior to occur and then we create the URL parameters and append them to the server URL. We then set src attribute of the iframe to that new URL. As a result, each time we submit the job, the src attribute will be updated and the iframe will execute the job.
Now that we have seen how the web page was created, it is time to see what the SAS code looks like.
SAS provides a macro to transform the parameters passed to the job. The macro is available here. I copied the macro code at the top of the SAS code and then wrote the following code that calls the macro to create two macro variables: inTypes and inDriveTrains.
%param_list(mvar=types, outvar=inTypes, dlm=%str(,), quote=y)
%param_list(mvar=drivetrains, outvar=inDrivetrains, dlm=%str(,), quote=y)
I only did this for these two variables because they can return multiple values for the same parameter and we want to build a list of selected values to filter our graph.
The graph is generated with the following code:
ods graphics / reset width=6.4in height=4.8in imagemap;
proc sgplot data=SASHELP.CARS;
hbar Make / response=Invoice group=Type groupdisplay=stack;
xaxis grid;
where type in (&inTypes) and drivetrain in (&inDrivetrains) and horsepower < &horsepowerMax and MSRP < &priceMax;
run;
ods graphics / reset;
As you can see, the macro variables are used in the where clause to do the filtering of the data.
As we have seen in the previous articles, one of the goals of the SAS Viya API Wrappers for JS is to allow the same code to be executed from the SAS Job Execution web interface as in the demo or from a standalone web application. In this example, there is no need to update the program or the form action when moving the web page from the SAS Viya Job HTML form to a standalone application. The reason is simple. In the previous example, we first submitted the job from the attached HTML form. As a result, we could use some specific parameters for the action and for the program name. In this article, we have already made these changes to display the result of the job on the same page. This makes it even easier to migrate the web page from the job definition to a standalone server.
While the code doesn't need to be modified to migrate to a standalone web application, the CORS configuration of the environment needs to allow connections to SAS Viya from a remote location. Therefore, you need to adjust the CORS configuration properly if the server name of the web server hosting your web application is different from the SAS Viya server name. For more information about CORS configuration, see the following articles:
Configure Cross-Origin Resource Sharing for SAS Viya for REST API’s an... - SAS Support Communities
All about CORS and CSRF for developing web applications with the SAS Visual Analytics SDK
Using the SAS Viya API Wrappers for JS makes it easy to create simple or advanced forms for SAS Viya jobs. With this library, you can focus on the user experience and designing the UI you want. The library hides the complexity of retrieving data from SAS to populate HTML elements with dynamic data. You can design your interface the way you want and just transparently retrieve data from the server.
The code for this example can be found here.
If you have ideas about how to improve the library code, please don't hesitate to contact me.
Articles in this series are:
SAS Viya API Wrappers for JS – Building dynamic prompts for SAS Viya Jobs
SAS Viya API Wrappers for JS – Building advanced dynamic prompts for SAS Viya Jobs (this article)
SAS Viya API Wrappers for JS – Building a Data Filtering and Display Application with React
Find more articles from SAS Global Enablement and Learning here.
Catch the best of SAS Innovate 2025 — anytime, anywhere. Stream powerful keynotes, real-world demos, and game-changing insights from the world’s leading data and AI minds.
The rapid growth of AI technologies is driving an AI skills gap and demand for AI talent. Ready to grow your AI literacy? SAS offers free ways to get started for beginners, business leaders, and analytics professionals of all skill levels. Your future self will thank you.