Skip to content

Programmatically add row to DnyamicRows component

I’m trying to programmatically add a row to a dynamic-rows component by extending the dynamic-rows and form components.
When an inserted form is submitted, the form data is inserted into the programmatically added row.

My code successfully adds a new row, and inserts the data into the input. So the new row and its input is visible, and the data is inserted into the input.
The problem is, it doesn’t save correctly, it just reverts back to whatever the was there before (if anything)
It also doesn’t allow you to add new rows after, and if you attempt to delete any row in the table, that row and the inserted row are removed.

I believe the issue has something to do with the way the template binds data ($data) to the processingAddChild method located in Magento_Ui/templates/dynamic-rows/templates/default.html and Magento_Ui/js/dynamic-rows/dynamic-rows.js

<button if="element.addButton"
        attr="{disabled: disabled, 'data-action': 'add_new_row'}"
        type="button"
        click="processingAddChild.bind($data, $false, false, false)">
    <span translate="addButtonLabel"></span>
</button>

Just to see what would happen, I changed the click method from processingAddChild.bind($data, $false, false, false) to console.log($data).
$data appears to be equivalent to this inside of the dynamic-rows component.

The inserted form component:

define([
    'jquery',
    'uiRegistry',
    'Magento_Ui/js/form/form',
], function ($, registry, form) {
    'use strict';
    return form.extend({
        defaults: {
            customFormData: {},
            exportTarget: 'myvendor_modulename_name_space_form.myvendor_modulename_name_space_form.test.items',//changed this but it does work
            exportTargetProperty: 'setImportedData',//export to method in dynamic-rows.js
            exports: {
                customFormData: '${ $.exportTarget }:${ $.exportTargetProperty }'
            },
            tracks: {
                customFormData: true
            }
        },
        initialize: function () {
            this._super();
        },

        getCustomFormData: function () {

            //make sure required fields are set
            this.validate();
            let missingRequired = this.source.get('params.invalid');
            if (missingRequired) {
                this.focusInvalid();
            }
            //when this is set, the data is exported to exportTargetFactory
            this.customFormData = registry.get('myvendor_modulename_name_space_form.inserted_form_data_provider').data;

        }
    })
})

The extended DynamicRows component:

define([
    'jquery',
    'uiRegistry',
    'Magento_Ui/js/dynamic-rows/dynamic-rows',
], function ($, registry, dynamicRows) {
    'use strict';
    return dynamicRows.extend({
        initialize: function () {
            this._super();
        },
        setImportedData: function (data) {
            let index = this.recordData().length //number of records
            //format to use later
            let formatted = {record_id: index, item: JSON.stringify(data)}
            let newRecordData = this.recordData();
            newRecordData.push(formatted)//add my data to recordData

            //set recordData
            this.recordData(newRecordData);//the value of the input won't be set without this
            this.processingAddChild(this,index,false)//add the child
        },
    })
})

I’ve left the xml out of this, but if it’s important, I can add it. Any suggestions would be greatly appreciated.