650 words
3 minutes
To build an Entity Metadata Lookup in Dynamics 365 CE using Web resources(Iframe)

To build an Entity Metadata Lookup in Dynamics 365 CRM using Web Resources, using below:
- Use
Xrm.Navigation.navigateTo
for dialog to display list of Entities - Passing the target CRM field dynamically via form parameters (
data=fieldName=...
) - Retrieve entity metadata using Webapi call to
/api/data/v9.2/EntityDefinitions
- Filter the retrieved result using
filter
- Write the selection back to the correct CRM field using
window.top.globalformContext
To build an Entity Metadata Lookup in Dynamics 365 CE using Web resources(Iframe) with Dynamic Field Binding
In this tutorial, I will walk you through the steps to build a custom entity metadata lookup using HTML + JavaScript web resources in Dynamics 365 CE. This component allows users to search for and select an entity (table) from metadata and write the selected logical name to any form field dynamically.
File Name and Usage
File | Purpose |
---|---|
lookup.html | Embedded on the CRM form to show the selected entity and button to open dialog |
lookup.js | To Open dialog and to return selected entity |
lookup_dialog.html | Modal dialog to show entity list from Webapi |
lookup_dialog.js | Logic to Load metadata, filter, and to return selected entity |
Folder Structure
WebResources/
├── lookup.html
├── lookup.js
├── lookup_dialog.html
└── lookup_dialog.js
lookup.html
to show the selected entity and the button to open lookup dialog
<!DOCTYPE html>
<html>
<head>
<title>Entity Metadata Lookup</title>
<script src="lookup.js"></script>
</head>
<body onload="initializeLookup()">
<div class="label">Entity Name</div>
<div class="container">
<div id="selected-entity">No entity selected</div>
<button onclick="clearData()" id="clear-button">X</button>
<button onclick="openLookupDialog()">Select Entity</button>
</div>
</body>
</html>
lookup.js
to handle logic to display the crm field value and to display the selected entity based on the selection returned from the dialog
let selectedEntityField = "";
let formContext = null;
function initializeLookup() {
const params = new URLSearchParams(window.location.search);
const rawData = decodeURIComponent(params.get("data") || "");
const parsedData = Object.fromEntries(new URLSearchParams(rawData));
selectedEntityField = parsedData.fieldName;
var interval = setInterval(() => {
if (window.top.OrchestratorFormContext) {
clearInterval(interval);
formContext = window.top.OrchestratorFormContext;
if (formContext?.getAttribute(selectedEntityField)) {
document.getElementById("selected-entity").innerText = formContext.getAttribute(selectedEntityField).getValue();
}
}
}, 2000);
}
function clearData() {
if (formContext && formContext?.getAttribute(selectedEntityField)) {
formContext.getAttribute(selectedEntityField).setValue(null);
document.getElementById("selected-entity").innerText = "";
}
}
function openLookupDialog() {
if (selectedEntityField === "") {
alert("Please select an entity field.");
return;
}
const pageInput = {
pageType: "webresource",
webresourceName: "anuprakash_entity_lookup_/lookup_dialog.html",
data: ""
};
const navigationOptions = {
target: 2,
width: 700,
height: 400,
position: 1
};
parent.Xrm.Navigation.navigateTo(pageInput, navigationOptions).then((result) => {
if (result && result.returnValue?.selectedEntity) {
debugger;
const entity = result.returnValue;
document.getElementById("selected-entity").innerText = entity.selectedEntity.logicalName;
if (formContext?.getAttribute(selectedEntityField)) {
formContext.getAttribute(selectedEntityField).setValue(entity.selectedEntity.logicalName);
}
}
});
}
lookup\_dialog.html
to display the entity metadata results as html table
<!DOCTYPE html>
<html>
<head>
<title>Select Entity</title>
<script src="lookup_dialog.js"></script>
</head>
<body onload="initializeDialog()">
<input
type="text"
id="searchBox"
placeholder="Search entities..."
oninput="filterEntities()"
/>
<table border="1" id="entityTable" class="floating-header">
<thead>
<tr>
<th>Display Name</th>
<th>Logical Name</th>
</tr>
</thead>
<tbody id="entityTableBody"></tbody>
</table>
</body>
</html>
lookup\_dialog.js
to handle logic to display the entity metadata results and to return the selected entity on click of table row
let allEntities = [];
function initializeDialog() {
fetchEntities().then(data => {
allEntities = data;
renderTable(allEntities);
});
}
async function fetchEntities() {
const url = parent.Xrm.Utility.getGlobalContext().getClientUrl() + "/api/data/v9.2/EntityDefinitions?$select=LogicalName,DisplayName,IsCustomEntity";
const response = await fetch(url, {
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
"Accept": "application/json",
"Content-Type": "application/json; charset=utf-8",
"Prefer": "odata.include-annotations=*"
},
credentials: "same-origin"
});
const json = await response.json();
return json.value.map(e => ({
logicalName: e.LogicalName,
displayName: e.DisplayName?.UserLocalizedLabel?.Label ?? e.LogicalName
}));
}
function renderTable(entities) {
const tbody = document.getElementById("entityTableBody");
tbody.innerHTML = "";
entities.forEach(entity => {
const tr = document.createElement("tr");
tr.innerHTML = `<td>${entity.displayName}</td><td>${entity.logicalName}</td>`;
tr.style.cursor = "pointer";
tr.onclick = () => selectEntity(entity);
tbody.appendChild(tr);
});
}
function filterEntities() {
const search = document.getElementById("searchBox").value.toLowerCase();
const filtered = allEntities.filter(item =>
item.displayName.toLowerCase().includes(search) ||
item.logicalName.toLowerCase().includes(search)
);
renderTable(filtered);
}
function selectEntity(entity) {
window.returnValue = { selectedEntity: entity };
window.close();
}
Add lookup.html
to Your Form
-
Go to the CRM form editor
-
Add
lookup.html
as a Web Resource -
In the “Custom Parameters (data)” box, set:
fieldName=anup_entityname
💡Replace
anup_entityname
with the schema name of your CRM field.
Conclusion and Output Video
Step | Action |
---|---|
1 | lookup.html is added to form and receives fieldName=... |
2 | lookup.js reads that field name dynamically |
3 | Opens lookup_dialog.html using Xrm.Navigation.navigateTo() |
4 | User selects entity from metadata table |
5 | Dialog closes and returns { id, name } |
6 | lookup.js sets CRM field value using window.top.globalformContext |
Screenshot of the Custom Control
GitHub Repository to the Code and Solution
You can find the full code here:
👉 anu-prakash-dev/d365-ce-entity-metadata-lookup
To build an Entity Metadata Lookup in Dynamics 365 CE using Web resources(Iframe)
https://crmte.ch/posts/entitylookup/