Model-Driven Apps (MDAs) in Microsoft Dataverse are powerful, but they are also opinionated. Microsoft intentionally limits direct access to the application shell, global lifecycle events, and certain UI elements.
Despite this, real-world projects often require behavior that goes beyond what is officially supported: hiding global buttons, initializing logic at app startup, or injecting custom UI.
This article describes two practical (but unsupported) techniques to work around these limitations:
Manipulating the DOM after the app loads
Executing JavaScript when the Model-Driven App opens by editing the app XML
Disclaimer
Both techniques rely on undocumented or unsupported behavior. Use them cautiously and expect breaking changes after platform updates.
1. Hacking the DOM After Load (Polling the Shell)
The Problem
Some global UI elements—such as the Quick Create button—cannot be hidden using supported APIs or command bar rules. They exist outside the form context and are rendered dynamically by the application shell.
The Idea
Instead of relying on supported events, we:
Inject an HTML web resource
Access the top-level document (
window.top.document)Poll the DOM until the target element appears
Modify or hide it directly
Example: Hiding the Quick Create Button
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Hide Quick Create</title>
<script>
(function () {
function hideQuickCreate() {
try {
const btn = window.top.document.querySelector(
"button[data-id='quickCreateLauncher']"
);
if (btn) {
btn.style.display = "none";
return true;
}
} catch (e) {
console.log(e);
}
return false;
}
const interval = setInterval(() => {
if (hideQuickCreate()) {
clearInterval(interval);
}
}, 500);
})();
</script>
</head>
<body></body>
</html>
Why This Works
The app shell loads asynchronously
The button is injected after initial page load
Polling ensures the script runs after the element exists
Risks & Limitations
DOM structure and
data-idvalues are not guaranteedCross-frame access may be blocked in future versions
Performance impact if polling is abused
This approach is best suited for small, targeted UI tweaks where no supported alternative exists.
Running JavaScript When a Model-Driven App Loads (Undocumented OnLoad)
The Problem
Model-Driven Apps do not officially expose a global onLoad event like forms do.
There is no supported way to run JavaScript when the app itself opens.
Yet sometimes you need exactly that:
Initialize global variables
Show notifications
Open dialogs or side panels
Perform app-level configuration
The Undocumented Solution
Model-Driven Apps internally support event handlers at the app level, configured in the app’s XML definition.
This is not documented—but it works.
What Is a Panel?
A panel is a static side pane that appears across all pages in a Model-Driven App and displays a web page from a URL.
Microsoft officially supports loading panels via:
Xrm.Panel.loadPanel(url, title);
Triggering Code at App Startup
Step 1: Create a JavaScript Web Resource
Example use case: load a side panel when the app opens.
var MEA = MEA || {};
MEA.Apps = MEA.Apps || {};
MEA.Apps.SalesHub = {
onLoad: function () {
Xrm.Panel.loadPanel(
"https://www.youtube.com/embed/VIDEO_ID",
"Now Playing"
);
}
};
Step 2: Export the Solution
Create a solution containing the Model-Driven App
Export it as unmanaged
Extract the ZIP file
Step 3: Edit customizations.xml
Locate the <AppModule> node and add the following:
<EventHandlers>
<EventHandler
eventname="onload"
functionname="MEA.Apps.SalesHub.onLoad"
libraryname="mea_/Scripts/SalesHub.js"
parameters=""
enable="true" />
</EventHandlers>
This configuration tells the platform to execute your JavaScript function when the Model-Driven App loads.
Step 4: Repack and Import
Re-zip the solution files
Import the solution back into Dataverse
Once imported, your JavaScript runs automatically at app startup.
Why This Works
Internally, Model-Driven Apps use the same event pipeline as forms.
The platform already supports app-level event handlers—Microsoft just hasn’t documented or officially exposed them.
This behavior was likely inspired by internal features such as Teams Calls integration introduced in Dynamics 365 Sales Wave 1 (2021).
Both approaches demonstrate a common reality in enterprise projects:
Sometimes business requirements move faster than platform features.
DOM hacking gives you quick UI control
XML-based app onLoad unlocks powerful startup logic