Customise Power Pages form fields

This post highlights key considerations when customising basic and multistep form fields in Power Pages

Visibility of a form field (Dataverse column)

Issue: Hiding a Dataverse column directly in Dataverse likely prevents it from appearing in the form’s DOM

Solution: Instead of relying on Dataverse settings, dynamically control form field visibility using jQuery within the form’s custom JavaScript


Presentation of a form field

Issue: The label of a form field appears in bold, however it should display with normal weight

Solution: Add a custom CSS rule for that particular form field. E.g.

label#cpl_portaluser_label { font-weight: normal; }

This ensures the label is rendered without bold styling


Read-only form field

Issue: When certain Dataverse form fields are set to read-only either via Dataverse or jQuery i.e. …prop(“disabled”, true), any value populated via JavaScript may not be saved on form submission. This occurs because the browser treats the field as non-editable, assuming user input was never intended

Solution: For Dataverse columns with a Currency data type, use CSS to visually disable the field while ensuring JavaScript populated values persist.

//in a CSS file
#cpl_portalusertitle {
    pointer-events: none;
    background-color: #f0f0f0;
    opacity: 0.6;
}


//or in a JavaScript file
$("#cpl_portalusertitle").css({
    "pointer-events": "none",
    "background-color": "#f0f0f0",
    "opacity": "0.6"
});

For Dataverse column with a Choice datatype, the following code makes the column read only on the form. This includes the scenario where the user tabs to the column on the form and tries to change the value by pressing the down arrow. The function would be called using the syntax setChoiceFieldAsReadOnly(“cpl_portalusertitle”);

function setChoiceFieldAsReadOnly(fieldId) {
    try {
        var $contributoryFactors = $(`#${fieldId}`);
        $contributoryFactors
            .attr("aria-disabled", "true")
            .off("keydown keyup keypress mousedown mouseup click")
            .on("keydown keyup keypress", function (e) {
                e.preventDefault();
                e.stopImmediatePropagation();
                return false;
            })
            .on("mousedown mouseup click", function (e) {
                e.preventDefault();
                e.stopImmediatePropagation();
                return false;
            });
    } catch (e) {
        console.error("Error in setChoiceFieldAsReadOnly:", e);
    }
}

For Dataverse column with a Date and time datatype, the following can be applied

  • Set the column to read-only in Dataverse, then use Multistep Form Metadata for the attribute to predefine the value (e.g. today’s date) and to ensure correct handling on save
  • Or, to set a Dataverse Date and time column as readonly using JavaScript, the following can be applied
$("#cpl_applicationlodgementdate_datepicker_description").prop("readonly", true).css({
	"pointer-events": "none",
	"opacity": "0.7"
});

For Dataverse columns with a Single line of text data type,

  • If populating the column via JavaScript, apply the following jQuery (line 1) to mark the field as readonly which will keep its value editable via JavaScript. Note: if the following jQuery (line 2) has been applied, the entered value won’t be saved to Dataverse because the browser seems to assume there is nothing to save.
$("#cpl_portaluser").prop("readonly", true);
$("#cpl_portaluser").prop("disabled", true);
  • If populating the column via metadata, apply the following jQuery to mark the field as readonly. Note: setting to “disabled” means the control isn’t highlighted when it’s clicked on.
$("#cpl_portaluser").prop("disabled", true);

Btw, to remove the border around the Single line of text on the form, use the following CSS

#cpl_portaluser {
    border: none !important;
}    

For Dataverse columns with a Yes/no data type,

  • If setting the column via JavaScript, on a multistep form, the following can be applied
$("#cpl_applicationnotlisted").on("click", function (e) {e.preventDefault();}).css({"accent-color": "gray", "pointer-events": "none", "user-select": "none" });

For Dataverse columns with a Lookup data type, the following code makes the column read only on the form. This includes the scenario where the user tabs to the column on the form and tries to change the value by pressing the down arrow or the delete button. The function would be called using the syntax setLookupFieldAsReadOnly(“cpl_providerid_name”);

function setLookupFieldAsReadOnly(fieldId) {
    try {
        // Lookup Name - make text field readonly, keep border, prevent editing
        var $lookupFieldId = $(`#${fieldId}`);
        $lookupFieldId
            .prop("readonly", true)
            .css({
                "pointer-events": "none",
                "user-select": "none"
            })
            .attr("tabindex", -1);
        // Disable lookup buttons for Lookup
        var $LookupButtons = $(`#${fieldId}`)
            .closest(".input-group")
            .find(".input-group-append, .input-group-addon, button, a, i");
        $LookupButtons
            .css({
                "pointer-events": "none",
                "user-select": "none",
                opacity: "0.5",
            })
            .attr("tabindex", -1)
            .attr("aria-disabled", "true")
            .off("keydown keyup keypress mousedown mouseup click")
            .on("keydown keyup keypress", function (e) {
                e.preventDefault();
                e.stopImmediatePropagation();
                return false;
            })
            .on("mousedown mouseup click", function (e) {
                e.preventDefault();
                e.stopImmediatePropagation();
                $(this).blur();
                return false;
            })
            .on("focus", function (e) { $(this).blur(); });
        // Also block all keyboard input in lookup field
        $lookupFieldId
            .on("keydown keyup keypress", function (e) {
                e.preventDefault();
                e.stopImmediatePropagation();
                return false;
            })
            .on("focus", function (e) { $(this).blur(); });
    } catch (e) {
        console.error("Error in setLookupFieldAsReadOnly:", e);
    }
}

Validation of conditionally mandatory form field

Issue: A Dataverse column that needs to be conditionally mandatory cannot be set as required directly within Dataverse

Solution: Implement page validation to enforce conditional mandatory rules


Static text stored in a form field

Issue: Read-only static text needs to be displayed on a multistep form. Below are four possible solutions

Solution 1: add multistep form metadata type = Attribute

  • Create a metadata entry for this form field
    • Metadata type = Attribute
    • Select the form field where the text should appear
    • Add Description: Yes (….or use the Prepopulate Field option)
    • Position: ‘Above the field’, ‘Below the field’ or ‘Above the label’
    • Description: Enter the static text to be displayed

Solution 2: Use a Dataverse column

  • Create a Dataverse column to store the text:
  • Populate either by
    • Metadata type = Attribute (this is recommended as it will appear in the Power pages studio)
    • In the form’s custom JavaScript, assign the desired static text to this column (this can include the \n escape sequence).

Solution 3: Use a Dataverse column (where italics, bold etc are required)

  const solvencyDeclarationSectionHeading = `The <i>solvency declaration</i> may be made directly below or provided via an attached statutory declaration. One of the following checkboxes must be selected.`;

  $("#cpl_portal_solvencydeclarationsectionheading").closest("td").find("div.table-info, span").first().html(solvencyDeclarationSectionHeading);
  $("#cpl_portal_solvencydeclarationsectionheading").prop("disabled", true);

Solution 4: Use a web resource (contained in an iframe)


Regular expression applied to a form field

Issue: A post code field requires validation to ensure only valid entries are accepted

Solution: add multistep form metadata type = Attribute

  • Select the form field where the regex expression needs to be applied to
  • Create a metadata entry for this form field
    • Metadata type = Attribute
    • Add the regex expression. For example, the following regular expression ensures the post code is valid
^(0[289][0-9]{2}[1-9][0-9]{3})$

Change event generated by a form field

Issue: Custom logic needs to be triggered when either of the following are controls are updated on the form

  • a Dataverse choices form field
  • a Dataverse subgrid

Solution: Implement two mutation observers to detect changes in each control and execute the required logic accordingly

Note:

Regarding the Dataverse choices form field, a couple of applications of using an observer could be:

  • to hide certain choices from the user
  • to trigger an event handler when a certain choice is selected by the user

Regarding the Dataverse subgrid, an application could be:

  • to trigger an event handler when a record is added to the subgrid

Further Reading

Enhance power pages forms functionality with jquery methods

References

to do