HTML web resources can be embedded into a CRM form within an iFrame. Often you'll need to send data to and from the embedded HTML page. Here's how.

If you need to send data from an HTML page to a CRM form, you can use window.parent to access the Xrm namespace. For example, a user may enter a value into an input field on your embedded HTML page which could then update a value on a CRM form automatically by using:

<script>
  var userInput = document.getElementById("input").value;
  window.parent.Xrm.Page.getAttribute("description").setValue(userInput);
</script>

Sending data the other way (from a CRM form to an HTML resource) is slightly more complicated.

Firstly, when customising your form and adding the embedded HTML resource, ensure that cross-frame scripting is not disabled (which it is by default). If this option is left checked you'll receive a sandboxed script cross-originerror message in the browser console, and the script won't load on the form.

Secondly, set up the data you want to send from your CRM form in JavaScript. This example sends a contact's first and last name in their respective onChange() events:

var iFrame = Xrm.Page.ui.controls.get('IFRAME_WebResourceName').getObject();

function firstNameOnChange() {
    var firstName = Xrm.Page.getAttribute("firstname").getValue();
    iFrame.contentWindow.postMessage({ 'firstname': firstName }, '*');
}

function lastNameOnChange() {
    var lastName = Xrm.Page.getAttribute("lastname").getValue();
    iFrame.contentWindow.postMessage({ 'lastname': lastName }, '*');
}

More on window.postMessage() can be found on MDN here.

Finally, configure your HTML page to accept and process messages from your CRM form. Place the following script tag in your HTML's body:

<script>
    window.addEventListener('message', function(event) {
        // Important. Only accept messages from trusted origins.
        if (~event.origin.indexOf('https://<yourCRMUrl>')) {
            var messageData = event.data;
          
            if (messageData.firstname) 
                document.getElementById("firstNameInput").value = messageData.firstname;                
            if (messageData.lastname)
                document.getElementById("lastNameInput").value = messageData.lastname;
        } else {
            return;
        }
    })
</script>

Here's the finished example: