Wednesday, July 30, 2014

How to conditionally hide, disable, and make mandatory fields on SharePoint forms dynamically

Here I'd like to demonstrate the most popular cases you may face during implementation of SharePoint forms with complex logic. Most likely you will need to combine the cases described below to cover your requirements but it's quite easy if you have enough samples. To accomplish the tasks below I used SharePoint Forms Designer 2.8.10. All samples work properly for all editions of SharePoint 2010/2013 including Foundations and Office 365.

First of all, I'd like to make an important notice which is common for all the cases. fd.field() method of JavaScript framework expects an internal name of a field you want to retrieve. As you might know, it's not easy enough to obtain an internal name of a field in SharePoint, so we included this property into field properties in Forms Designer 2.8.10:

Internal name of SharePoint field

Now you can just copy and paste it into your code in a much simpler way even without closing Forms Designer. OK, let me start.

Prepopulate field and disable/enable it based on condition

Let's say we have a task form and we need to set the Percent Complete to 100% and disable it when the user turns the Status field into Completed:

SharePoint conditional fields

We should place the following code into JS-editor of Forms Designer:

function setPercentComplete() {
    if (fd.field('Status').value() == 'Completed') {
        // Setting the Percent Complete to 100
        fd.field('PercentComplete').value('100');

        // Getting JQuery-object of the field and disable it
        fd.field('PercentComplete').readonly(true);
    } else {
        // Getting JQuery-object of the field and enable it
        fd.field('PercentComplete').readonly(false);
    }
}

// Calling setPercentComplete when the user changes the status
fd.field('Status').change(setPercentComplete);

// Calling setPercentComplete on form loading
setPercentComplete();

// Enabling fields before the submission
fd.onsubmit(function () {
    fd.field('PercentComplete').readonly(false);
    return true;
});

Please, pay attention to the last part of the code:

// Enabling fields before the submission
fd.onsubmit(function () {
    fd.field('PercentComplete').readonly(false);
    return true;
});

Most browsers don’t send values of disabled fields to the server during the submission, so they will be lost. Therefore, we need to enable all fields that we need to save right before the submission in onsubmit handler.

Hide/show field or set of fields conditionally

Now I will modify the script from the previous section so that it will hide the Percent Complete field. First, we should assign a CSS-class to the field to use it in JQuery-selector:

Assign CSS-class to SharePoint field

OK, now we can use it to retrieve the field container by the following way: $('.percent-complete'). Here is the modified code:

function setPercentComplete() {
    if (fd.field('Status').value() == 'Completed') {
        // Setting the Percent Complete to 100
        fd.field('PercentComplete').value('100');

        // Getting JQuery-object of the field container and hide it
        $('.percent-complete').hide();
    } else {
        // Getting JQuery-object of the field container and show it
        $('.percent-complete').show();
    }
}

// Calling setPercentComplete when the user changes the status.
fd.field('Status').change(setPercentComplete);

// Calling setPercentComplete on form loading
setPercentComplete();

Please, notice that I've removed the last part from the code because values of hidden fields are passed to the server properly.

What if we need to hide multiple fields? There are several approaches. You can either put them into a single table and assign CSS-class to the table:

Assign CSS-class to multiple SharePoint fields

Next, use that class in JQuery-selector to retrieve the table and hide or show it:

// Hide the table
$('.fields-to-hide').hide();

// Show the table
$('.fields-to-hide').show();

Or if your fields are scattered about the form and you cannot put them into a single table, you can assign the same CSS-class to all fields that you need to hide e.g. 'field-to-hide' and use it in the selector to make all of them disappear:

$('.field-to-hide').hide();

Require field based on condition

At this section I'd like to demonstrate how to make some fields mandatory based on other field values. Let's go back to the original task form and say that we need to make the Due Date field required if the task is assigned to someone (the Assigned To field is not empty).

Here is the sample:

function setRequiredFields() {
    if (fd.field('AssignedTo').value().dictionaryEntries.length != 0) {
        // Add asterisks
        fd.field('DueDate').titleRequired(true);
    } else {
        // Remove asterisks
        fd.field('DueDate').titleRequired(false);
    }
}

// Calling setRequiredFields when the user changes the assignment
fd.field('AssignedTo').change(setRequiredFields);

// Calling setRequiredFields on form loading
setRequiredFields();

// Custom validation
fd.onsubmit(function () {
    if (fd.field('AssignedTo').value().dictionaryEntries.length != 0) {
        if (!fd.field('DueDate').value()) {
            alert('Please, fill in the Due Date field.');
            return false;
        }
    }

    return true;
});

As you can see, I've added the custom validation into onsubmit handler, whereas fd.field().titleRequired() just adds or removes the asterisk near the title.

Get values on display forms

Finally, I'd like to focus your attention on differences between display and edit or new forms. Display forms don't contain controls, so you can retrieve only the text representation of field values like you see them on a form. The samples above work on new and edit forms only. You should use the following syntax to obtain a text representation of values on a display form:

fd.field('Status').control()._el().text()

Get information on how to get or set values of different types of fields from the following article: http://formsdesigner.blogspot.com/2013/04/getting-and-setting-sharepoint-form.html

Please, feel free to ask your questions in comments.