Tag Archives: tabs

Microsoft Dynamics 365: Counting Sub-grid Records and Enabling Users to Hide Empty Sub-grids

In Microsoft Dynamics 365, we can use sub-grids to present data to users in a tabular format. This is a nice and compact way of displaying data. However, sometimes there is no data in those sub-grids to display and the end users might prefer to get back that space and optimize the space on the form. In this blog post, we cover how we can dynamically obtain the number of records in a sub-grid using JavaScipt and use that information to give end users the flexibility to optimize the space on forms by hiding empty sub-grids.

There are two types of sub-grids on Dynamics 365 forms:

  • Read-only sub-grids: Show data in a tabular format but do not allow users to edit data directly on the sub-grid. To edit the data, users have to double click on the record in the grid to open the form, edit the data, and then save it.
  • Editable sub-grids: Apart from showing data in a tabular format, editable sub-grids offer rich inline editing capabilities on web and mobile clients including the ability to group, sort, and filter data within the same sub-grid so that you do not have to switch records or views. In addition to providing all these extensive editing capabilities, editable sub-grids still honor the read-only sub-grid metadata and field-level security settings as well as the general Microsoft Dynamics 365 security model.

Summary of the key syntax

Here is a high-level summary of the main Microsoft Dynamics 365 JavaScript syntax covered in this blog post.

  • Count the number of records in sub-grid, where <subgridName> is the logical name of the sub-grid :
    formContext.getControl("<subgridName>").getGrid().getTotalRecordCount();
  • Remove the blank option in an option set, where <optionsetName> is the logical name of the option set:
    formContext.getControl("<optionsetName>").removeOption("");
  • Get the option set’s selected value , where <optionsetName> is the logical name of the option set:
    formContext.getAttribute("<optionsetName>").getValue();
  • Set the selected value of an option set, where <optionsetName> is the logical name of the option set and <value> is the value the option set will be set to:
    formContext.getAttribute("<optionsetName>").setValue("<value>");
  • Enable/Disable a field, where <fieldName> is the logical name of the field and <Boolean> can be true or false (i.e. true disables field and false enables it):
    formContext.getControl("<fieldName>").setDisabled(<Boolean>);
  • Hide/Unhide section, where <nameOfTab> is the name of the tab containing the section, <nameOfSection> is the name of the section and <Boolean> can be true or false (i.e. true makes the section visible and false hides the section):
    formContext.ui.tabs.get("<nameOfTab>").sections.get("<nameOfSection>").setVisible( <Boolean>);

Application Example: Enabling Users to Hide Empty Sub-grids

Using the code below, we can give end users the flexibility to optimize the space on forms by hiding empty sub-grids. In the code below, the hideEmptyOfficesSubgrid function is the entry point and is called when saving the form and loading the form.

function hideEmptyOfficesSubgrid(executionContext) {  
    var formContext = executionContext.getFormContext();
    var operationsTabName = "tab_operations";
    var officeGridSectionName = "office_grid_section";
    var officeGridName = "office_subgrid";
    var enableOfficeGridName = "hos_enableofficesgrid";
    var no = 183840000;
    var yes = 183840001;
    formContext.getControl(enableOfficeGridName).removeOption(""); 

    setTimeout(function () {
        if (formContext.getControl(officeGridName) != null && formContext.getControl(officeGridName) != undefined) {
            var count = formContext.getControl(officeGridName).getGrid().getTotalRecordCount();
            var enableOfficeGrid = formContext.getAttribute(enableOfficeGridName);
            var enableOfficeGridCtrl = formContext.getControl(enableOfficeGridName);
            var officeGridSection = formContext.ui.tabs.get(operationsTabName).sections.get(officeGridSectionName);
            disableSubgridControlField(count, enableOfficeGridCtrl);
            hideEmptySubgrid(count, enableOfficeGrid, officeGridSection, no, yes);
        }
    }, 5000);      
}

function disableSubgridControlField(count, subgridCtrlField) {  
    if (count <= 0) 
        subgridCtrlField.setDisabled(false);       
    else if (count > 0) 
        subgridCtrlField.setDisabled(true);
}

function hideEmptySubgrid(count, subgridCtrlField, subgridSection, no, yes) {  
    if (areTheseTwoInputsIdentical(subgridCtrlField.getValue(), yes)) 
        subgridSection.setVisible(true);       
    else if (count <= 0 && (areTheseTwoInputsIdentical(subgridCtrlField.getValue(), no) || subgridCtrlField.getValue() == null)) 
        subgridSection.setVisible(false);
    else if (count > 0 && areTheseTwoInputsIdentical(subgridCtrlField.getValue(), no)) {
        subgridCtrlField.setValue(yes);
        subgridSection.setVisible(true);
    }
}

function areTheseTwoInputsIdentical(input1, input2) {
    if (input1 == input2) 
        return true;
    else 
        return false;
}

How the code works

In the first image below, the account record is not enabled for Offices (i.e. the value of Enable Office Grid option set is No). Therefore, Offices grid is empty and hidden.
Account record not enabled for Offices sub-grid

After enabling the account record for Offices by changing the value of the option set field, “Enable Offices Grid” to Yes, the Offices sub-grid shows up and we can add offices to the sub-grid as shown below. The “Enable Offices Grid” field controls the appearance and disappearance of the Offices sub-grid.
Account record enabled for Offices sub-grid

As shown in the image above, the Enabled Office Grid option set is locked as soon as we add and save records to the Offices sub-grid. This prevents a scenario of logic inconsistency where an account record has offices in it’s sub-grid and the user proceeds to change the value of the Enable Offices Grid field to No. Therefore, the Enable Office Grid field value can only be changed back to No and hide the Offices grid after the sub-grid emptied up and there are no more records in it. Therefore, using the solution above, end users can be empowered with the option of hiding empty sub-grids and optimize the space on the form.

Microsoft Dynamics 365: Varying Form Behavior On Form-type and Save-mode

Microsoft Dynamics 365 offers the ability to vary the behavior of forms based on the form type and how the form is saved, using JavaScript. In this blog post, we cover how we can make use of this flexibility offered by the platform to deliver unique solutions for end users.

Summary of the key syntax

Here is a high-level summary of the main Microsoft Dynamics 365 JavaScript syntax covered in this blog post.

  • Getting the type of form:
    formContext.ui.getFormType();
  • Hide a tab on a form (where “TabName” represents the name of the tab you would like to hide):
    formContext.ui.tabs.get("TabName").setVisible(false);
  • Get the object with methods to manage the Save event:
    executionContext.getEventArgs();
  • Get the form Save Mode:
    executionContext.getEventArgs().getSaveMode();
  • Inhibit the default save behavior on a form
    executionContext.getEventArgs().preventDefault();
  • Check if the default save behavior was inhibited
    executionContext.getEventArgs().isDefaultPrevented();
  • Get the form context
    executionContext.getFormContext();

Form Type

To get the Form Type, you use the following JavaScript code:

formContext.ui.getFormType();

Here are the different Dynamics 365 form types and their respective JavaScript return values:

Form type Return Value
Undefined0
Create1
Update2
Read Only3
Disabled4
Bulk Edit6

Application Example: Varying form behavior on Form Type

In this application example, we will hide the Products and Services tab on the Create type form (with JavaScript Return Value = 1). However, it will be still be visible on all other applicable form types. This prevents users from adding information to the Products and Services tab before a Contact record has been created and saved. Therefore, the user must first create the Contact record (using the Create form type) and after the record has been created, the users will be presented with the Update form type (with JavaScript Return Value = 2) and will be able to access the Products and Services tab as well as its contents.

The Contact entity’s create form type will look similar to this (i.e. the Products and Services tab is hidden):
Contact - Create form type

In contrast, the Update form type still shows the Products and Services tab.
Contact - Update form type

Here is the code to executes the requirement above.

//Hide Products and Services tab on Create form 
function HideProductsServicesTab(executionContext) {   
  //Get form context   
  var formContext = executionContext.getFormContext();   
  //Get form type   
  var formType = formContext.ui.getFormType();   
  //If formtype is Create, hide Products and Services tab on form     
  if (formType == 1) {
    formContext.ui.tabs.get("productsandservices").setVisible(false);   
  }   
  //To see the form type return value in your browser console
  console.log("Form type = " + formType); 
}

Save Mode

To get the form’s Save Mode, you use the following JavaScript code:

executionContext.getEventArgs().getSaveMode();

Here are Dynamics 365’s different Save Modes and their respective JavaScript return values as well as the applicable entities.

Entity Save Mode Return Value
AllSave1
AllSave and Close2
AllDeactivate5
AllReactivate6
EmailSend7
LeadDisqualify15
LeadQualify16
User or Team owned entitiesAssign47
ActivitiesSave as Completed58
AllSave and New59
AllAuto Save70

Application Example: Varying form behavior on Save Mode

Here is an example of how you can vary the form’s behavior on the Save Mode.

//Inhibit auto save functionality on a form
function InhibitAutoSave(executionContext) {
  var eventArgs = executionContext.getEventArgs();
  //To see the Save Mode return value in your browser console
  console.log("Save Mode = " + eventArgs.getSaveMode());
  //If save mode is 'Save and Close' or 'Auto Save', inhibit default behavior i.e. save 
  if (eventArgs.getSaveMode() == 2 || eventArgs.getSaveMode() == 70) {
    eventArgs.preventDefault(); 
  } 
  //To see if the auto save behavior was prevented in your browser console
  console.log("Default behaviour prevented: " + eventArgs.isDefaultPrevented());
 }

If you have some unsaved changes on a form, the code above inhibits the regular form auto save behavior as well as inhibits the regular Save and Close auto save behavior, that you ordinarily get when you navigate away from from a form with unsaved changes. Instead of auto-saving (i.e. the default behavior), if you try to navigate away from a form with an unsaved changes, the JavaScript code above will block the auto save behavior and offer you the pop up notification below. If you choose “OK”, you will loose all your unsaved changes, and if you choose “Cancel”, you will remain the same form. With the default auto save behavior inhibited, users have to manually save the form, by clicking on the Save button or using the keyboard shortcut: “Control + S”.
Auto Save Inhibited: Do you want to loose your changes?

What if you want to inhibit the auto-save behavior throughout your Dynamics 365 organization (i.e. disable auto-save on all forms), instead of a specific form? It would be inefficient to implement the JavaScript code above on all forms across all your Dynamics 365 organization entities. An efficient way execute such a requirement (i.e. on all forms) is to:

  1. Go to Settings > Administration.
  2. Click on System Settings.
  3. Click on the General tab
  4. Set the Enable auto save on all forms option, to No.
  5. Click OK, in the footer of the window.

Disabling Auto Save in a Dynamics 365 Organization