This is similar to my earlier post (https://dreamingincrm.com/2015/10/27/using-sessionstorage-to-interact-with-iframe-in-crm-forms/) that discussed using sessionStorage events to interact with IFrame and the IFrame to interact with the ClientApiWrapper. ClientApiWrapper is the IFrame that hosts the form scripts. Here is the code I used.
IFrame
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Form IFrame</title> <script> window.addEventListener('message', function(e) { if(e.origin != parent.Xrm.Page.context.getClientUrl()) return; document.getElementById('messageFromParent').textContent = 'Parent says "' + e.data+'"'; }); document.addEventListener('DOMContentLoaded' , function() { document.getElementById("buttons").addEventListener("click", function(e){ var url = parent.Xrm.Page.context.getClientUrl(); var fieldName = document.getElementById("crmFieldName").value; switch(e.target.id){ case "enableField": parent.postMessage(['setFieldEditability', [fieldName,false]],url); break; case "disableField": parent.postMessage(['setFieldEditability', [fieldName,true]],url); break; case "hideField": parent.postMessage(['setFieldVisibility', [fieldName,false]],url); break; case "showField": parent.postMessage(['setFieldVisibility', [fieldName,true]],url); break; } }); }); </script> </head> <body> <p id="messageFromParent"></p><br><br> <input type="text" id="crmFieldName"><br><br> <div id="buttons"> <button id="enableField">Enable Field</button> <button id="disableField">Disable Field</button> <button id="hideField">Hide Field</button> <button id="showField">Show Field</button> </div> </body> </html>
Form Script
(function(){ var CVN = window.CVN || {}; var childChannel; parent.addEventListener('message', function(e) { if(e.origin != Xrm.Page.context.getClientUrl()) return; childChannel = e.source; CVN[e.data[0]].apply(null,e.data[1]); }, false); CVN.onSave = function(){ }; CVN.setFieldEditability = function(fieldName, isDisabled){ Xrm.Page.getControl(fieldName).setDisabled(isDisabled); if(childChannel) childChannel.postMessage(fieldName+' has been '+(isDisabled ? 'disabled' : 'enabled'),Xrm.Page.context.getClientUrl()); }; CVN.setFieldVisibility = function(fieldName, isVisible){ Xrm.Page.getControl(fieldName).setVisible(isVisible) if(childChannel) childChannel.postMessage(fieldName+' has been '+(isVisible ? 'hidden' : 'unhidden'),Xrm.Page.context.getClientUrl()); }; CVN.onLoad = function(){ }; window.CVN = CVN; })();
Screenshot
The eventhandler for message has to be attached to the parent for messages originating from both the form script (ClientApiWrapper) and the HTML webresource embedded into the form.
I envision the use of this technique primarily for form script -> html webresource communication, and common functions that are called by both form script and html webresource.
Reference: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage