A Deep Dive into Dashboard and Widget Preferences Management in 3DExperience

For developers and administrators transitioning from the classic Enovia V6 architecture to the modern Dassault Systèmes 3DEXPERIENCE platform, the shift in UI technology can feel like a paradigm leap. In the classic environment, almost everything was tightly coupled to the 3DSpace backend. If you needed to store a user’s setting, you relied on standard Matrix Query Language (MQL) or Java Program Objects (JPOs) to read and write properties directly against the user’s Matrix object in the database.

However, the modern 3DEXPERIENCE platform introduces the 3DDashboard—a sleek, widget-based interface built on a microservice architecture. Suddenly, developers realize that their standard MQL queries cannot find where a user’s dashboard settings are saved.

Where do these preferences live? How do you prevent users from having to re-configure their widgets every time they log in? In this comprehensive technical guide, we will dismantle the architecture of 3DDashboard preferences, explore the Universal Web App (UWA) API, and walk through real-world code implementations that you can apply to your next custom widget project.

The Architectural Shift: Decoupling from 3DSpace

To master widget preferences, you must first unlearn a core habit: Dashboard and Widget preferences are NOT stored in the standard 3DSpace database.

Because 3DEXPERIENCE relies on a modern microservice architecture, the front-end user experience is decoupled from the backend product data. Dashboards, tabs, and widget configurations are managed entirely by the 3DDashboard Service (often interacting with its own distinct foundational data stores, separate from the PLM business objects).

This architectural decision is brilliant for performance and scalability, but it introduces a specific rule that developers must understand: Persistency occurs at the Widget Instance level.

What is the Widget Instance Level?

Imagine an engineer named Sarah. Sarah creates a new dashboard tab and drags two instances of the out-of-the-box “Bookmark Editor” widget onto her screen.

  • In Widget A, she filters the view to show only “Released” documents and adjusts her column widths.
  • In Widget B, she filters the view to show “In Work” CAD models and switches to a thumbnail grid view.

If preferences were stored at the User level, modifying Widget A would overwrite the settings for Widget B. By storing preferences at the Widget Instance level, the 3DDashboard backend assigns a unique identifier to every single widget dropped onto a dashboard. When Sarah logs out and logs back in, the 3DDashboard service queries its database for those specific instance IDs, retrieving the unique configurations for both Widget A and Widget B perfectly intact.

The Developer’s Toolkit: The UWA API

Because widget preferences live outside of 3DSpace, you do not need to write complex Java web services or MQL scripts to manage them. Dassault Systèmes provides the UWA (Universal Web App) JavaScript API to handle this seamlessly on the client side.

When you define a custom widget, you declare your preferences in the widget’s HTML header. Once declared, the UWA framework automatically handles the backend database transactions. When you use JavaScript to update a preference locally, the framework silently pushes that update to the 3DDashboard backend via REST, ensuring it is saved for the next session.

The Three Types of Preferences

When building a widget, you will typically rely on three types of preferences:

  1. User-Facing Preferences (Text, Boolean, List): These automatically populate the “Preferences” menu (the gear icon) on the widget window, allowing the user to configure the app themselves.
  2. Hidden Preferences: These do not show up in the UI gear menu. They are used by developers to silently save the state of the app (like column widths, last searched term, or active tab) without cluttering the user’s settings menu.
  3. Administrator Configurations: Default JSON payloads injected when an app is registered to the platform.

Let’s look at how to implement these in real-world scenarios.

Real-World Scenario 1: The Configurable Data Filter (User-Facing)

The Business Problem:

You are developing a “My Critical ECOs” (Engineering Change Orders) widget. A department manager wants to put this widget on their dashboard, but they only want to see ECOs assigned to a specific “Collaborative Space” (e.g., the “Chassis Engineering” space).

Instead of hardcoding the Collaborative Space into your JavaScript, you need to expose this as a user preference so the manager can change it via the widget’s settings menu.

Step 1: Declaring the Preference in the Widget XML/HTML

At the top of your widget’s HTML file, you define the preference block. We will create a list type preference that allows the user to select their desired space.

XML

<widget>
    <preferences>
        <preference name="targetCollabSpace" type="list" label="Filter by Collab Space" defaultValue="all">
            <option value="all" label="All Spaces" />
            <option value="ctx::VPLMProjectLeader.MyCompany.Chassis_Engineering" label="Chassis Engineering" />
            <option value="ctx::VPLMProjectLeader.MyCompany.Powertrain" label="Powertrain" />
        </preference>
        
        <preference name="strictMode" type="boolean" label="Enable Strict Filtering" defaultValue="false" />
    </preferences>
</widget>

Note: The UWA framework will automatically read this block and generate a beautiful UI form when the user clicks the “Preferences” gear icon on the widget.

Step 2: Reading the Preference in JavaScript

When your widget loads, you need to fetch the value the user selected and append it to your REST API call to 3DSpace. You accomplish this using widget.getValue().

JavaScript

/* global widget */
define('MyCustomECOApp/Main', ['UWA/Core', 'DS/WAFData/WAFData'], function (UWA, WAFData) {
    'use strict';

    var ECOApp = {
        
        init: function () {
            // Retrieve the stored preference from the 3DDashboard backend
            var selectedSpace = widget.getValue('targetCollabSpace');
            var isStrict = widget.getValue('strictMode');

            console.log("Widget initialized. Target Space: " + selectedSpace);
            
            // Call our function to load data based on the preference
            ECOApp.fetchECOData(selectedSpace, isStrict);
        },

        fetchECOData: function(space, strict) {
            var myRestEndpoint = "/resources/v1/eco/list?space=" + space + "&strict=" + strict;
            // ... Execute AJAX call to 3DSpace using WAFData ...
        }
    };

    // Initialize when the widget is ready
    widget.addEvent('onLoad', ECOApp.init);
    
    // CRITICAL: Listen for when the user changes the preference in the menu!
    widget.addEvent('onRefresh', ECOApp.init);
    
    return ECOApp;
});

By binding the onRefresh event to our init function, the widget will automatically reload the data the second the user hits “Save” in the preferences menu.

Real-World Scenario 2: Persisting UI State (Hidden Preferences)

The Business Problem:

You have built a beautiful custom widget that displays a bill of materials (BOM). The user has the option to view this BOM as a “List” or a “Grid”. Furthermore, they can type a search string into a local search bar to filter the list.

Users are complaining that every time they refresh the page or log in the next morning, the widget defaults back to the “List” view, and their search string is cleared. They want the widget to remember exactly how they left it.

You cannot put this in the user-facing settings menu (it would be annoying for a user to open a settings menu just to change from list to grid). It needs to happen dynamically.

Step 1: Declaring Hidden Preferences

We define preferences in the widget header, but we omit the label and set the type to hidden. This tells the platform to store the data, but keep it out of the user’s gear menu.

XML

<widget>
    <preferences>
        <preference name="savedViewMode" type="hidden" defaultValue="list" />
        <preference name="lastSearchTerm" type="hidden" defaultValue="" />
    </preferences>
</widget>

Step 2: Dynamically Setting Preferences in JavaScript

When the user clicks the button in your UI to change the view to “Grid”, you must not only change the DOM, but you must also execute widget.setValue() to silently push this new state to the database.

JavaScript

define('MyBOMApp/UIControls', ['UWA/Core'], function (UWA) {
    'use strict';

    var UIControls = {

        setupEventListeners: function () {
            
            // Assume we have a toggle button in our HTML with ID 'view-toggle-btn'
            var toggleBtn = document.getElementById('view-toggle-btn');
            
            toggleBtn.addEventListener('click', function() {
                // Determine what the new state should be
                var currentMode = widget.getValue('savedViewMode');
                var newMode = (currentMode === 'list') ? 'grid' : 'list';
                
                // Update the UI immediately for a snappy UX
                UIControls.renderView(newMode);
                
                // SILENTLY SAVE THE PREFERENCE TO THE BACKEND
                // The UWA framework handles the REST call to 3DDashboard automatically
                widget.setValue('savedViewMode', newMode);
                
                console.log("State saved. Next time user logs in, view will be: " + newMode);
            });

            // Assume we have a search input with ID 'local-search-input'
            var searchInput = document.getElementById('local-search-input');
            
            searchInput.addEventListener('change', function(e) {
                var searchTerm = e.target.value;
                
                // Save the search term when the user finishes typing
                widget.setValue('lastSearchTerm', searchTerm);
            });
        },

        restoreStateOnLoad: function() {
            // When widget boots up, read the hidden prefs and restore UI
            var savedMode = widget.getValue('savedViewMode');
            var savedSearch = widget.getValue('lastSearchTerm');
            
            UIControls.renderView(savedMode);
            document.getElementById('local-search-input').value = savedSearch;
        }
    };

    return UIControls;
});

This is the hallmark of enterprise-grade widget development. By utilizing hidden preferences, you create a seamless, stateful application that feels like a native desktop app, drastically improving user satisfaction and reducing daily friction.

The Administrator’s Perspective: Default Configurations via JSON

While developers use the UWA API and users utilize the graphical interface, Platform Administrators have their own method for managing preferences at scale.

When an administrator registers a custom widget on the 3DEXPERIENCE platform (navigating to the “Additional Apps” or “App Management” dashboard), they provide the URL to the widget’s HTML file. However, they are also presented with an optional field: Configuration File URL.

This is incredibly powerful. The Configuration File is a simple JSON document hosted on your server that dictates the default values for the widget’s preferences before the user ever touches it.

Example config.json:

JSON

{
    "preferences": {
        "targetCollabSpace": {
            "value": "ctx::VPLMProjectLeader.MyCompany.Chassis_Engineering",
            "locked": true 
        },
        "strictMode": {
            "value": "true",
            "locked": false
        }
    }
}

Notice the "locked": true parameter? By deploying a configuration file, an administrator can force a preference onto a widget and prevent the end-user from overriding it.

If you are deploying a “Chassis Release Dashboard” to 500 engineers, you do not want them accidentally changing the target Collaborative Space and looking at the wrong data. By utilizing the JSON configuration file during app creation, you lock the targetCollabSpace preference globally for that specific App ID, while leaving other preferences (like view modes) unlocked for personal customization.

Conclusion

Understanding the boundary between the 3DSpace backend and the 3DDashboard frontend is the first major hurdle for 3DEXPERIENCE developers. Once you realize that dashboard preferences are isolated, instance-specific data points managed by the UWA framework, the architecture transforms from a confusing black box into a highly flexible toolset.

By mastering <preference> declarations in your widget headers and strategically deploying widget.getValue() and widget.setValue() in your JavaScript, you can build dynamic, state-aware applications. Whether you are building configurable data filters for management or simply ensuring an engineer’s column widths stay exactly where they left them, embracing the client-side preference API is the key to delivering a world-class user experience on the 3DEXPERIENCE platform.

Vivek Agrawal

Vivek Agrawal is dedicated to exploring the core themes of engineeringplm.com and trending product lifecycle management (PLM) topics. His research covers a variety of highly relevant 2026 trends, including the shift from AI copilots to autonomous agentic workflows, real-time IoT, and Digital Twin integration. Vivek also analyzes the evolving role of PLM in ESG tracking, specifically regarding Digital Product Passports. From unpacking the complexities of event-driven architectures to deep dives on real-time syndication between PLM and Product Information Management (PIM), he provides the insights necessary to navigate the 2026 product development landscape.

Leave a Reply

Your email address will not be published. Required fields are marked *