When analyzing hierarchical data in SAS Visual Analytics, you can create hierarchies which give the end-user the opportunity to drill into the data and display the information based on the defined hierarchy. Another way to visualize hierarchical data is to use an organization chart, often referred to as an org chart. SAS Visual Analytics does not have an out-of-the-box object like an org chart, but you can use the Data-Driven Content object to leverage a custom-built visualization or a third-party open-source option.
The Data-Driven Content object requires you to create an HTML page with JavaScript to handle the data received from the Visual Analytics report. While JavaScript handles the Visual Analytics data provided by SAS (see documentation or Github), you need to use a framework to create the visualization. You have many different open-source options: D3 Org Chart, Google Org Chart, ... These options are fine and meet the needs of many companies. Nevertheless, I decided to demonstrate that you can build a simple organization chart using React framework and simple Material UI objects.
The React component that will be created has a simple logic. It receives data from SAS Visual Analytic and transforms the set of data into a flattened tree. When displaying the report, the user sees the top element (parent) and its children. When the user clicks on a node, the node is selected, and the selection is passed back to SAS Visual Analytics to filter other objects in the report which might be linked to the Data-Driven Content object. In my custom org chart visualization, the user can drill up and down using arrows. The component has a breadcrumb which indicates where the user is in the data structure. Each node will also have a small badge indicating how many children nodes are bound to it.
Here is a demo to clarify the functionalities.
As you can see the choice has been made to use the org chart as a filter tool and not to display data in the object itself. There are good reasons for that related to how the Data-Driven Content (DDC) object works. The data set is passed to the DDC object as an array of data at the lowest level, a bit like a detailed table but aggregated based on the variable selection. As a result, it is complex or impossible to recreate the proper calculation in the Data-Driven Content object. For example, if a measure uses "average" as aggregation type, it is impossible to recreate the average for each level as the average of averages is rarely equal to an average calculated based on the detailed data. Recreating the averages for each level would imply passing the detailed data which is stored in the CAS table to the DDC object and calculating the average in the DDC object. For this reason, only the categories can be passed to the component I've created.
TypeScript is a superset of JavaScript and enforces type checks. While you develop in TypeScript, you can find yourself a bit frustrated at the beginning because it requires you, as a developer, to define the proper variable types when defining variables or functions. This is not common for JavaScript or Python developers because these languages are weakly typed which means that the language will assign the variable types when interpreting the code. TypeScript works differently, you write your code with the variable types defined and then you transpile your JavaScript. Transpiling is not like compiling the code in Java. It is a translation of TypeScript to JavaScript. In that process, the transpiler will check the variable types and throw errors whenever needed. As a result, you can detect errors in your code before it is used. Though it can be frustrating to see errors, it ensures that the variable types are consistent, that you are adding the logic to check if the variable is defined and has a non-null value. In addition, editors like Visual Studio Code can also check the syntax and the variables before transpiling which means you get hints about the variable types while editing your code. If you are a JavaScript developer and want to know more about TypeScript, please refer to this introduction.
In this article, I will not cover how the DDC object works as there are many articles already covering the topic. If you are new to SAS Visual Analytics and especially to Data-Driven Content, I suggest you read one of my earlier articles or look for Data-Driven Content:
I will just mention that I will be using the JavaScript snippets described in SAS Help Center: Programming Considerations for Data-Driven Visualizations. The component will use the concepts described in "Receiving Data", "Selection Handling" and "Custom Instructional Message" section of the documentation
To create the component, I've used TypeScript version of React. If you prefer to use plain JavaScript, you can also do it. I've chosen to code in TypeScript because it is commonly used for web developments, and it forces the developer to write better code by enforcing type checks. This article assumes you are familiar with React and TypeScript. This application uses ViteJS to host the development environment. ViteJS has been configured to use React and TypeScript. Please follow these instructions to initialize the project. You should then add Material UI to your project. This can be achieved by following these instructions. If you prefer, you can copy the code of the application from xavierBizoux/sas-org-chart (github.com) and execute npm command to install all the dependencies.
The application has been created using create-react-app. The structure is the one provided by the script. In addition to the default structure, a few folders have been created to define the different components, functions as well as interfaces which are used in the application.
Select any image to see a larger version.
Mobile users: To view the images, select the "Full" version at the bottom of the page.
The interfaces include the TypeScript interface's definitions. These interfaces are used to define the function signatures and store the information needed for TypeScript to enforce type checking. If you want to know more about interfaces in TypeScript, please refer to this documentation.
If you are not familiar with TypeScript, you may have noticed that some variables are defined with a question mark. This indicates that the variable is optional in the interface. As TypeScript will check the signature, TypeScript will transpile the code properly even if a variable is missing and marked as optional.
With the interfaces in place, we also need a few functions to handle the data received from the VA report and to send messages back to filter data in the report or to inform the user that the correct data has not been passed to the DDC object. The functions are:
This function will transform the array of data received from VA into a flattened tree which is used later to display the different nodes in the organizational chart. As you can see at the beginning, some interfaces are used to define new variables. As a result, when passing data from one function to the other, we are sure that the data type is correct, and that the data contains the expected set of variables.
This function identifies how many levels we have in the data received from VA. This is done by looping through the columns array provided by VA and checking the variable type. If the type is not string, then the process stops and sends a message to the end-user that "Only categorical variables are supported!".
This function is responsible for sending messages to VA. The message is defined as an interface and can have different content as defined in the interface. If the message variable is defined, it informs the user about something. If the selections is filled in, it will send the filter information to the VA report which will then filter dependent objects.
As we have seen above, the sendMessageToVA function can send a list of selected rows back to the VA report for filtering. This selection needs to be created and this is the role of this function. As the data used in the organization chart doesn't have the structure as the data received from VA, the selection list needs to be created by finding all the descendants from the selected node.
Now that you have seen the functions, it is interesting to check the different components in the user interface. We have two components and the application itself which will act as a wrapper for the other components.
The component uses the Card component from Material UI. Here, I've decided to define the INodeProps interface inside the component as it is specific to it and not used outside of the component. The definition may seem a bit long because it has a bit of logic to handle the display of the top and down arrows used for navigation in the tree. The cardStyle variable defines the style that is applied to the node if it is selected or not. It adds a border around the box to emphasize that it was selected.
This component is based on the Breadcrumbs component from Material UI. It appears in the top left of the application based on the level the user is currently in. It also gives the opportunity to navigate to a specific level when clicking on it.
This is the longest code in the application as it will group all the other components and functions. It also defines the interactions between the elements. I will focus here on the different important snippets and will not cover the import statements for example.
At the top of the App function, we are defining the states which are used to store data but also trigger updates to the user interface when they change.
The first useEffect is probably the most important as it is the one which defines the process to receive the data from the report and to build the data structure used to display the nodes in the organization chart. It defines an event listener which triggers the creation of the tree data as soon as the data is passed to the DDC object.
The second useEffect sets the information needed to display the interface when the data is loaded from VA.
The third useEffect handles the navigation in the tree. It is called whenever the top element in the chart is changing.
The fourth useEffect handles the selection process. When the selected node changes, it builds the selection which is then passed to the VA report using sendMessage function to filter dependent objects in the VA report.
The navigationHandler is the function which handles the navigation between the various levels.
The visualization part is the responsibility of the last bit of code.
This snippet uses the Box and Grid elements from Material UI. It defines how the elements should position on the screen. Please note that the positioning is dynamic based on the available space for the DDC object. It means that you may see more or less children nodes on a row depending on the DDC size.
This application is created using create-react-app. When you are developing the application, you can start the development server using npm start. As soon as you want to integrate with SAS Viya, you need to make sure that the development server is running on HTTPS. You should also make sure that the CORS and CSRF are properly configured for your environment. You can find information about CSRF and CORS in the following article: Configure Cross-Origin Resource Sharing for SAS Viya for REST API’s and web developments.
To deploy the application, you need to build the application using npm or yarn build commands. It will create a build folder on your project, and you can then deploy that folder into your preferred web server on the production environment. If you want to know how it can be done, please refer to the following article: Deploy a custom web application in the cloud for Data-Driven Content object in SAS Viya 4.
When building reports, you may discover that the visual you are looking for is not available in SAS Visual Analytics yet. Do not feel intimidated to create your own visualization. You can use available components from third-party frameworks like D3JS, Google chart or you can build your own visualization using a framework like React or even pure JavaScript.
In this article, I tried to show you how you can use TypeScript, React, and Material UI to build a web application. The objective is clearly not to teach you to program for the web. The objective is to demonstrate how to proceed and that you can do it using different techniques. If you prefer to develop using Angular, Vue, jQuery or any other framework, it is also possible. You can use your preferred framework or no framework at all. The benefit of using a framework is that you can leverage the work that has been done by others before in such a way that you don’t need to waste a lot of time reinventing the wheel.
I hope you enjoyed reading this article. If you have ideas or requests for other custom visualizations, please don’t hesitate to share them as comments to this article. I will be happy to help you or guide you in the process of creating your own visualization.
Find more articles from SAS Global Enablement and Learning here.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
Data Literacy is for all, even absolute beginners. Jump on board with this free e-learning and boost your career prospects.