Open HTML web resource on button click and pass data to web resource and display related records in table with paging, checkbox from dynamics 365
You can use JavaScript and Client API to open HTML web resource from Dynamics 365 Forms and pass data parameters to the web resource, read the parameter and fetch records using fetchXML from javascript in web resource. The below screenshot shows how the html web resource looks like when button is clicked.
Watch video below otherwise scroll down for code and details.
Now let us see how you can proceed step by step.
Requirement
I want to place a custom button on Account form and on clicking the button an html web resource will open which will display related contacts of the account record.
Solution
For this you need to create one JavaScript web resource and another HTML web resource. The JavaScript web resource will be called on button click and the JS web resource will call HTML web resource and pass account id to html web resource. In the HTML web resource we will use XRM.WebAPI methods to read related contacts. Follow these steps.
We will use OpenWebResouce and XRM.WebAPI client APIs for this article.
Step 1 : Create JS web resource
Create a JavaScript web resource and paste the code given below.
function ShowRelatedContacts(primaryControl)
{
var formContext = primaryControl;
var accountID = formContext.data.entity.getId();
var webresourceName = "crcfa_contactsws.html";
var windowOptions = { height: 600, width: 700 };
Xrm.Navigation.openWebResource(webresourceName, windowOptions, accountID);
}
Step 1 : Create HTML web resource
Create a HTML web resource and put the below code.
<html><head><meta></head><body onfocusout="parent.setEmailRange();">
<script src="../WebResources/ClientGlobalContext.js.aspx" type="text/javascript"></script>
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://cdn.datatables.net/1.11.5/js/jquery.dataTables.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" type="text/css">
<link href="https://cdn.datatables.net/1.11.5/css/dataTables.bootstrap.min.css" rel="stylesheet" type="text/css">
<link href="//cdn.datatables.net/1.11.5/css/jquery.dataTables.min.css" rel="stylesheet" type="text/css">
<script>
<!-- Read Window URL -->
var url = window.location.href;
<!-- Process The Data From URL -->
var dataIndex = url.lastIndexOf("=") + 1;
var dataLenght = url.length;
var recordData = url.slice(dataIndex,dataLenght);
var processedRecordData = recordData.replace("%20","").replace("%7b","").replace("%7d","");
var fetchXml = "?fetchXml=<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>"+
"<entity name='contact'>"+
"<attribute name='contactid' />"+
"<attribute name='fullname' />"+
"<attribute name='transactioncurrencyid' />"+
"<attribute name='preferredcontactmethodcode' />"+
"<attribute name='statecode' />"+
"<attribute name='jobtitle' />"+
"<order attribute='fullname' descending='false' />"+
"<filter type='and'>"+
"<condition attribute='parentcustomerid' operator='eq' uitype='account' value='{@accountid}' />"+
"</filter>"+
"</entity>"+
"</fetch>";
fetchXml = fetchXml.replace("@accountid",processedRecordData);
Xrm.WebApi.retrieveMultipleRecords("contact", fetchXml).then(
function success(result) {
var t1 = "<table id='tblwo' style='width:100%;background-color:#f0f0f0' class='display table table-striped table-bordered'> <thead><tr><th class='ckeck_1'><input id='checkboxAll' onclick='SelecDeselecAll()' type='checkbox'></th><th>Full Name</th><th> Currency</th><th>Preferred Contact</th><th>Status</th><th>Job Title</th></tr> </thead><tbody>@tr</tbody></table>";
var trr ="";
for (var i = 0; i < result.entities.length; i++) {
trr = trr + "<tr><td><input id='checkbox"+ i + "' type='checkbox' class='chkNumber' value='"+result.entities[i].contactid+"' ></td><td>"+result.entities[i].fullname +"</td><td>"+result.entities[i]['_transactioncurrencyid_value@OData.Community.Display.V1.FormattedValue']+"</td><td>"+result.entities[i]['preferredcontactmethodcode@OData.Community.Display.V1.FormattedValue']+"</td><td>"+result.entities[i]['statecode@OData.Community.Display.V1.FormattedValue']+"</td><td>"+result.entities[i].jobtitle +"</td></tr>";
}
t1 = t1.replace("@tr",trr);
document.getElementById("pp").innerHTML=t1;
$('#tblwo').DataTable( {
"pageLength": 3,
"pagingType": "numbers",
"bLengthChange": false,
"bFilter": true,
"bInfo": false,
"searching": false
} );
},
function (error) {
console.log(error.message);
// handle error conditions
}
);
function SelecDeselecAll() {
if ($('#checkboxAll').prop('checked')) {
$('#tblwo')
.find('input[type="checkbox"]')
.prop('checked', true);
}
else {
$('#tblwo')
.find('input[type="checkbox"]')
.prop('checked', false);
}
}
function Activate() {
var chkId = '';
var selector = $('.chkNumber:checked');
var i = 0;
$(selector).each(function () {
i = i + 1;
chkId = $(this).val();
document.getElementById("sts").innerHTML ="Activation Process Started. Please wait..";
UpdateRecord(chkId,0,1);//status, status reason
document.getElementById("sts").innerHTML ="Records Activated.";
});
}
function DeActivate() {
var chkId = '';
var selector = $('.chkNumber:checked');
var i = 0;
$(selector).each(function () {
i = i + 1;
chkId = $(this).val();
document.getElementById("sts").innerHTML ="De-Activation Process Started. Please wait..";
UpdateRecord(chkId,1,2);//status, status reason
document.getElementById("sts").innerHTML ="De-Activation Process Completed.";
});
}
var globalContext = window.parent.Xrm.Utility.getGlobalContext();
function UpdateRecord(id,status, startusreason) {
var record = {};
record.statecode = status; // State
record.statuscode = startusreason; // Status
var req = new XMLHttpRequest();
req.open("PATCH", globalContext.getClientUrl() + "/api/data/v9.2/contacts(" + id + ")", false);
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Prefer", "odata.include-annotations=*");
req.onreadystatechange = function () {
if (this.readyState === 4) {
req.onreadystatechange = null;
if (this.status === 204) {
console.log("Record status updated");
} else {
alert(this.responseText);
}
}
};
req.send(JSON.stringify(record));
}
function UpdateCurrency() {
var chkId = '';
var selector = $('.chkNumber:checked');
var i = 0;
$(selector).each(function () {
i = i + 1;
chkId = $(this).val();
document.getElementById("sts").innerHTML ="Currency Update Process Started. Please wait..";
UpdateCurrencyLookupAsUSD(chkId);//id of contact
document.getElementById("sts").innerHTML ="Currency Update Process Completed.";
});
}
function UpdateCurrencyLookupAsUSD(id) {
var curr = "cf8b234e-2798-ec11-b400-000d3a300c9c"; //USD currency id
var data =
{
"transactioncurrencyid@odata.bind": "/transactioncurrencies("+curr+")"
}
Xrm.WebApi.updateRecord("contact", id, data).then(
function success(result) {
//alert("Currency Updated successfully");
},
function error(result) {
alert(error.message);
});
}
function UpdateJobTitle() {
var chkId = '';
var selector = $('.chkNumber:checked');
var i = 0;
$(selector).each(function () {
i = i + 1;
chkId = $(this).val();
document.getElementById("sts").innerHTML ="Job Title Update Process Started. Please wait..";
var data =
{
"jobtitle":$('#txtJobTitle').val()
}
Xrm.WebApi.updateRecord("contact", chkId, data).then(
function success(result) {
//alert("Currency Updated successfully");
},
function error(result) {
alert(error.message);
});
document.getElementById("sts").innerHTML ="Job Title Update Process Completed.";
});
}
</script>
<h4>Employees <button class="btn btn-sm btn-success" onclick="window.location.reload();">Refresh</button></h4><hr>
<p id="sts" style="padding-left:20px"></p>
<p id="pp" style="padding:20px;max-height:400px;overflow:auto"></p>
<div class="container" > <div class="row"><div class="col-2" ></div><div class="col-12" >
<button class='btn btn-primary' onclick="Activate();"> Activate</button>
<button class='btn btn-dark' onclick="DeActivate();"> DeActivate</button>
<button class='btn btn-dark' onclick="UpdateCurrency();"> Update USD Currency</button>
</div></div> </div>
<div class="container bg-warning" style="padding:20px;max-height:400px;overflow:auto" class="bg-light">
<h4>Job Title</h4>
<input type="text" id="txtJobTitle" />
<button class='btn btn-dark' onclick="UpdateJobTitle();"> Update Job Title</button>
</div>
</body></html>
Step 3 – Create a custom button
using Model app designer or ribbon workbench add a custom button on Account form and call the JS web Resource on click of button.
Now When you run the model driven app and open sales hub account form you will see the button and on clicking the button the web resource will open with page enabled using jquery datatable.
Also checkboxes are available for the records so that you can select rows and change the record status using buttons available. you can also update lookup field, display formatted lookup text, option set text, choice text etc in this demo.
Follow my blog for more trending topics on Dynamics 365, Azure, C#, Power Portals and Power Platform. For training, Courses and consulting, call to us at +91 832 886 5778 I am working more for community to share skills in Dynamics 365 and Power Platform. Please support me by subscribing my YouTube Channel. My YouTube Channel link is this : https://www.youtube.com/user/sppmaestro
Hope this helps.