Skip to content

Adding sections and tabs

Daryl LaBar edited this page Nov 14, 2024 · 4 revisions

Tabs

Tabs can be added after initialising the UI (calling XrmMockGenerator.initialise). The following method will add a tab to the form:

const isTabVisible = true;
const tabParent = null; // you practically never need to specify a parent
let sections = [];
let tab = XrmMockGenerator.Tab.createTab("tabLogicalName", "Tab Label", isTabVisible, "expanded", tabParent, sections);

Sections

Sections are added to tabs, just like the typical CRM form structure. You should add sections during tab creation as follows:

const isSectionVisible = true;
// 'null' indicates the section is going to be added to the tab below (section array as argument)
const sectionParent = null;
const controls = [];
sections =
   new ItemCollectionMock<Xrm.Controls.Section>(
      [
         XrmMockGenerator.Section.createSection("sectionLogicalName", "Section Label",
            isSectionVisible, sectionParent, controls);
      ]);
tab = XrmMockGenerator.Tab.createTab("tabLogicalName", "Tab Label", isTabVisible, "expanded", tabParent, sections);

Examples

The following examples use Vitest to mock the relevant functions.

Please note these tests use JavaScript and not TypeScript like other tests documented in this wiki.

This example demonstrates a basic client-side script running on a Account form in Dynamics. When the form is loaded, the script:

  • gets the value of the toggle field.
  • shows the section if the value of the field is show.
  • hides the section if the value of the field is not show.

account.js

export default class Account {
  // Table - in this example, we are working with the Account table

  // OnLoad events
  static onLoad(executionContext) {
    "use strict";

    // On Load events - execute toggleSectionVisibility function.
    Account.toggleSectionVisibility(executionContext);
  }

  static toggleSectionVisibility(executionContext) {
    "use strict";
    var formContext = executionContext.getFormContext();
    var toggleValue = formContext.getAttribute("toggleField").getValue();

    if (toggleValue === "show") {
      formContext.ui.tabs
        .get("tabName")
        .sections.get("sectionToToggle")
        .setVisible(true);
    } else {
      formContext.ui.tabs
        .get("tabName")
        .sections.get("sectionToToggle")
        .setVisible(false);
    }
  }
}

account.test.js

import Account from "../src/account";
import { describe, it, expect, beforeEach, vitest } from "vitest";
import { ItemCollectionMock, XrmMockGenerator } from "xrm-mock";

describe("Account", () => {
  beforeEach(() => {
    XrmMockGenerator.initialise();

    // Setup the tab and section
    const isTabVisible = true;
    const tabParent = null;
    const sectionParent = null;
    const controls = [];
    const sections = new ItemCollectionMock([
      XrmMockGenerator.Section.createSection(
        "sectionToToggle",
        "Section Label",
        true,
        sectionParent,
        controls
      ),
    ]);

    const tab = XrmMockGenerator.Tab.createTab(
      "tabName",
      "Tab Label",
      isTabVisible,
      "expanded",
      tabParent,
      sections
    );
  });

  it("show a section when a the toggle value is 'show'", () => {
    const controlAttribute = XrmMockGenerator.Attribute.createString({
      name: "toggleField",
      value: "show",
    });

    const context = XrmMockGenerator.getEventContext();
    Account.onLoad(context);

    // Verify if sections are visible or not
    const formContext = context.getFormContext();
    const section = formContext.ui.tabs
      .get("tabName")
      .sections.get("sectionToToggle");

    expect(section.getVisible()).toBe(true);
  });

  it("hide a section when a the toggle value is not 'show'", () => {
    const controlAttribute = XrmMockGenerator.Attribute.createString({
      name: "toggleField",
      value: "don't show",
    });

    const context = XrmMockGenerator.getEventContext();
    Account.onLoad(context);

    // Verify if sections are visible or not
    const formContext = context.getFormContext();
    const section = formContext.ui.tabs
      .get("tabName")
      .sections.get("sectionToToggle");

    expect(section.getVisible()).toBe(false);
  });
});

Code explanation and walkthrough:

Import the relevant Vitest modules, in order to test and mock the notification functions.

import { describe, it, expect, beforeEach, vitest } from "vitest";

Import Account module. This module is compiled to JavaScript and added to the Contact form in Dynamics.

import Account from "../src/account";

Import XrmMockGenerator and ItemCollectionMock to run tests.

import { ItemCollectionMock, XrmMockGenerator } from "xrm-mock";

Initialise a global Xrm object and create required attributes to the fake Xrm object.

XrmMockGenerator.initialise();

// Setup the tab and section
const isTabVisible = true;
const tabParent = null;
const sectionParent = null;
const controls = [];
const sections = new ItemCollectionMock([
  XrmMockGenerator.Section.createSection(
    "sectionToToggle",
    "Section Label",
    true,
    sectionParent,
    controls
  ),
]);

const tab = XrmMockGenerator.Tab.createTab(
  "tabName",
  "Tab Label",
  isTabVisible,
  "expanded",
  tabParent,
  sections
);

const controlAttribute = XrmMockGenerator.Attribute.createString({
  name: "toggleField",
  value: "show",
});

// OR

const controlAttribute = XrmMockGenerator.Attribute.createString({
  name: "toggleField",
  value: "don't show",
});

Define the eventContext.

const context = XrmMockGenerator.getEventContext();

Invoke Account.onLoad and assert the expected outcome.

// Run the function to show / hide the section
Account.onLoad(context);

// Note that the `formContext` is captured post execution
const formContext = context.getFormContext();

const section = formContext.ui.tabs
  .get("tabName")
  .sections.get("sectionToToggle");

// Verify if sections are visible or not

expect(section.getVisible()).toBe(true);

// OR

expect(section.getVisible()).toBe(false);

Author: Yagasoft

Contributor: maichopra

Clone this wiki locally