I'm working on a front-end project with some relatively complex UI requirements for author dialog. The author UI requires field dependency. A set of fields is shown or hidden based on a certain selection author makes. After getting a working codes finalized, I thought that it is worth sharing with the community.

Sample use case for field dependency:

As a content author, I would like to be able to build a grid of maximum 12 columns. I would like to have 2 options: Default and Custom.

When I choose Default, I would like to see a set of fields including:

  • Dropdown list with predefined column formats like: 1 Column; 2 Columns (6, 6); 2 Columns (10, 2), etc.
  • Dropdown list with predefined column's border styles.
  • Dropdown list with predefined column's padding styles.

When I choose Custom, I would like to see a set of fields including:

  • Dropdown list with numbers of columns: 1, 2, 3, …, 12
  • When I choose any of the number from the dropdown, I would like to have a correspond number of text/number field set(s) that contained: column width, column padding, column border, etc, where I can manually enter a number (1, 2, 3,..., or 12) for each column width and enter css codes for each column padding (i.e. 10px 5px 10px 5px) and each column border.

Steps to take to achieve the above requirements:

  1. Obviously we need a dialog (see Figure 1)

    Figure 1.
  2. Under the dialog we need a tab and panel (i.e. configuration node of cq:Panel). Under configuration node, we need two specific properties of type String. Let's name them: toggleGridFormat and toggleColStyle ((see Figure 2)):

    Figure 2.
  3. Under the cq:WidgetCollection (items) of the configuration node, we need:
    1. A dropdown list for author to choose either Default or Custom. We need a listeners node (of nt:unconstructed) with properties as (see Figure 3):

      Figure 3.
    2. A fieldset contained fields for Default, which user can select different lists of predefined dropdown values like: numbers of columns, column padding, column border, etc...
    3. A fieldset contained fields for Custom. Under this field set we need:
      1. A dropdown list contained 12 options: 1, 2, 3, ..., 12. Under this dropdown list, we need a listeners node with properties (see Figure 4).

        Figure 4.
      2. A fieldset contained 12 hidden compositefield lists of fields (see Figure 5). Each list of compositefield contained fields for: column width, column padding, column border, etc…

        Figure 5.
  4. Your component's JSP file that handles the logic to display grid based on author's selection.

Detailed code for Figure 2:

The value for toggleGridFormat property:

function (v)
{
    var p;
    var format = v === 'default' ? './defaultLayout' : './customLayout';
    var toggledStyleOpts = false;

    $CQ.each(this.find('gridFormatOptions'), function(index, elem) {
        p = elem.findParentByType('dialogfieldset', true);
        if (p && p.id === 'gridFormatOptions' && elem.name)
        {
            if (elem.name.toString() === format)
            {
                elem.show();
            }
            else
            {
                elem.hide();
            }
        }
        else if (!toggledStyleOpts && p && p.id === 'colStyleOptions')
        {
            if (v === 'default')
            {
                p.hide();
            }
            else
            {
                p.show();
            }

            toggledStyleOpts = true;
        }
    });

    this.doLayout();
}

The value of toggleColStyle property:

function(n)
{
    var p;
    var colStyle = [];

    for(var i = 1; i <= n; i++)
    {
        colStyle.push('col'+i+'Style');
    }

    var colStyleRegex = new RegExp(colStyle.join('|'), "i");

    $CQ.each(this.find('colStyleOptions'), function(index, elem) {
        p = elem.findParentByType('dialogfieldset');
        if (p && p.id === 'colStyleOptions')
        {
            if (elem.id.match(colStyleRegex))
            {
                elem.show();
            }
            else
            {
                elem.hide();
            }
        }
    });

    this.doLayout();
}

Detailed code for Figure 3:

The value of loadcontent property:

function()
{
    this.findParentByType('panel', true).toggleGridFormat(this.getValue());
}

The value of selectionchange property:

function()
{
    box.findParentByType('panel', true).toggleGridFormat(value);
}

Detailed codes Figure 4:

The value of loadcontent property:

function()
{
    this.findParentByType('panel', true).toggleColStyle(this.getValue());
}

The value of selectionchange property:

function(box, value)
{
    box.findParentByType('panel', true).toggleColStyle(value);
}