PHP 7.3 reaches end of support in December 2021 and Adobe Commerce 2.3.x reaches end of support in April 2022. You may want to consider planning your upgrade now to Adobe Commerce 2.4.x and PHP 7.4.x to help maintain PCI compliance.

RowBuilder widget

The RowBuilder widget allows you to build a container with rows.

The RowBuilder widget can be used only on the frontend area.

The RowBuilder widget source is lib/web/mage/row-builder.js.

Initialize the RowBuilder widget

For information about how to initialize a widget in a JS component or .phtml template, see the Initialize JavaScript topic.

The RowBuilder widget is instantiated with:

1
2
3
4
5
6
7
8
$("#row-builder").rowBuilder({
    "rowTemplate":"#row-template",
    "rowContainer":"#row-container",
    "rowParentElem":"<div></div>",
    "remEventSelector":"a",
    "btnRemoveSelector":".action.remove",
    "maxRows":"5"
});``

Where:

  • #row-builder is the selector of the element which will be the RowBuilder.

The following example shows a PHTML file using the script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script>
    require([
        'jquery',
        'rowBuilder'
    ], function ($) {
        'use strict';

        $("#row-builder").rowBuilder({
              "rowTemplate":"#row-template",
              "rowContainer":"#row-container",
              "rowParentElem":"<div></div>",
              "remEventSelector":"a",
              "btnRemoveSelector":".action.remove",
              "maxRows":"5"
        });
    });
</script>

The following example shows a PHTML file using the script with some data for a couple of fields:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<div class="row-builder-example">
    <div id="max-rows-message" style="display: none;" class="message notice limit" role="alert">
        <span>Number of rows exceeded.</span>
    </div>
    <button type="button" id="add-row-button" class="action add">
        <span>Add Item</span>
    </button>
    <div id="row-container"></div>
</div>

<script id="row-template" type="text/x-magento-template">
    <div>
        <div class="field name required">
            <label for="field1-name<%- data._index_ %>" class="label"><span>Item <%- data._index_ %> Field</span></label>
            <div class="control">
                <input name="field1[name][<%- data._index_ %>]" type="text" title="<?= $block->escapeHtmlAttr(__('Name')) ?>" class="input-text"
                       id="field1-name<%- data._index_ %>"/>
            </div>
        </div>
        <div class="field name required">
            <label for="field2-name<%- data._index_ %>" class="label"><span>Item <%- data._index_ %> Field</span></label>
            <div class="control">
                <input name="field2[name][<%- data._index_ %>]" type="text" title="<?= $block->escapeHtmlAttr(__('Name')) ?>" class="input-text"
                       id="field2-name<%- data._index_ %>"/>
            </div>
        </div>
        <div class="field name required">
            <label for="field3-name<%- data._index_ %>" class="label"><span>Item <%- data._index_ %> Field</span></label>
            <div class="control">
                <input name="field3[name][<%- data._index_ %>]" type="text" title="<?= $block->escapeHtmlAttr(__('Name')) ?>" class="input-text"
                       id="field3-name<%- data._index_ %>"/>
            </div>
        </div>
        <div class="actions-toolbar">
            <div class="secondary">
                <a href="#" id="btn-remove<%- data._index_ %>" class="action remove"
                   title="Remove Item">
                    <span>Remove Item</span>
                </a>
            </div>
        </div>
    </div>
</script>

<script>
    require([
        'jquery',
        'rowBuilder'
    ], function ($) {
        'use strict';

        var data = {
            formData: [
                ["field1-name1", "field2-name1", "field3-name1"],
                ["field1-name2", "field2-name2", "field3-name2"],
                ["field1-name3", "field2-name3", "field3-name3"],
                ["field1-name4", "field2-name4", "field3-name4"],
            ],
            templateFields: [
                "field1-name", "field2-name", "field3-name"
            ]
        };

        $(".row-builder-package-manager").rowBuilder({
            "rowTemplate": "#row-template",
            "rowContainer": "#row-container",
            "rowParentElem": "<div></div>",
            "remEventSelector": "a",
            "btnRemoveSelector": ".action.remove",
            "formDataPost": data
        });
    });
</script>

This is provided during widget instantiation. For example:

1
formDataPost : {"formData": ["field1-name1", "field2-name1", "field3-name1"], "templateFields":['field1-name','field2-name','field3-name']]}

-"formData" is the multi-dimensional array of form field values : [[‘a’,’b’],[‘c’,’b’]] received from the server and encoded

-"templateFields" are the input fields in the template with index suffixed after the field name. For example, field1-name{index}, field2-name{index}, field3-name{index}

Options

The PopupWindow widget has the following options:

rowTemplate

The row template selector.

Type: String

Default value: '#template-registrant'

rowContainer

The row container selector.

Type: String

Default value: '#registrant-container'

rowIndex

Row index used by the template rows.

Type: Integer

Default value: 0

rowCount

Row count.

Type: Integer

Default value: 0

rowParentElem

Row parent element.

Type: String

Default value: '<li></li>'

rowContainerClass

Row container class.

Type: String

Default value: 'fields'

addRowBtn

The add row button selector.

Type: String

Default value: '#add-registrant-button'

btnRemoveIdPrefix

ID prefix of a remove button.

Type: String

Default value: 'btn-remove'

btnRemoveSelector

The remove button selector.

Type: String

Default value: '.btn-remove'

rowIdPrefix

ID prefix of a row element.

Type: String

Default value: 'row'

additionalRowClass

The additional row class name which is added after the main class name.

Type: String

Default value: 'add-row'

addEventSelector

Default selectors for adding elements to a template.

Type: String

Default value: 'button'

remEventSelector

Default selectors for removing markup elements from a template.

Type: String

Default value: 'a'

hideFirstRowAddSeparator

This option specifies if the remove link and additional row class are removed for the first row.

Type: Boolean

Default value: true

maxRows

Max number of rows.

Type: Integer

Default value: 1000

maxRowsMsg

The message selector of an element which appears when the max number of rows has been exceeded.

Type: String

Default value: #max-registrant-message

Code sample

This example shows the row builder container, which adds a new row when you click the Add Item button and removes a row when you click the Remove Item button.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<script id="row-template" type="text/x-magento-template">
    <div>
        <div class="field name required">
            <label for="field-name<%- data._index_ %>" class="label"><span>Item <%- data._index_ %> Field</span></label>
            <div class="control">
                <input name="field[name][<%- data._index_ %>]" type="text" title="<?= $block->escapeHtmlAttr(__('Name')) ?>" class="input-text"
                       id="field-name<%- data._index_ %>"/>
            </div>
        </div>
        <div class="actions-toolbar">
            <div class="secondary">
                <a href="#" id="btn-remove<%- data._index_ %>" class="action remove"
                   title="Remove Item">
                    <span>Remove Item</span>
                </a>
            </div>
        </div>
    </div>
</script>

<div class="row-builder-example"
     data-mage-init='{
        "rowBuilder":{
            "rowTemplate":"#row-template",
            "rowContainer":"#row-container",
            "rowParentElem":"<div></div>",
            "remEventSelector":"a",
            "btnRemoveSelector":".action.remove",
            "maxRows":"5",
            "maxRowsMsg":"#max-rows-message",
            "addRowBtn":"#add-row-button",
            "additionalRowClass":"additional"
        }
     }'>
    <div id="max-rows-message" style="display: none;" class="message notice limit" role="alert">
        <span>Number of rows exceeded.</span>
    </div>
    <button type="button" id="add-row-button" class="action add">
        <span>Add Item</span>
    </button>
    <div id="row-container"></div>
</div>

Result

As a result, we see the RowBuilder widget example with 5 rows as max.

RowBuilder widget Example RowBuilder widget with warning message Example