Community Alums
Not applicable

Apparently if you have a multi-row variable set on a catalog item, there is no Out of box way to react to changes of rows; like row added, row removed or row updated from a client script, which is assigned to the catalog item.

We can define client scripts on the MRV itself, so we could react to field changes of a given row's fields, but this is still not enough to handle row addition on removal.

My workaround provides an easy approach to overcome this limitation.

Steps

  1. create a new widget, for example "MRV Macro widget"
  2. add this widget to the catalog item as a Macro variable (so it won't be visible on the form)
  3. set the script below as the client script of the widget and update according to your needs

Explanation

field.change event is emitted by the form component, for each and every field change of the form. The MRV basically is also a field, but it contains rows and cell values in a JSON-encoded array of objects.

Whenever the rows are changed within the MRV in any way (rows added / removed, or fields updated within the row) the same event will be broadcasted on $rootScope. So the widget will listen to this events, and whenever the event is broadcasted, with the name of the MRV, then we can do the required calculations.

This method requires no customisation to any OOTB widgets and in my opinion, yet it's able to overcome on the missing support for MRV row-level onChange client script support. Note: because of the embedded widget approach, this will work only in service portals!

Client script of the widget

api.controller = function($scope, $rootScope) {

    var c = this;

    c.onFieldChange = function(event, data) {

        var form = $scope.page.g_form;

        /**
         * Name of the MRV.
         * Update this according your own MRV's internal name
         */
        var fieldName = "name_of_mrv";
        var total = 0; // TODO: delete this, just an example


        /**
         * If the function is executed for a real "field.change" event, 
         * let's react only if the MRV was changed
         */
        if (event && data) {
            if (data.field.name != fieldName) {
                return;
            }
        }


        try {
            /**
             * Let's try to get the field's value and parse it as JSON
             */
            var rows = JSON.parse(form.getValue(fieldName))

            /**
             * Rows here now, should be an array of objects, each object represents 1 row from the MRV,
             * and objects' properties are the variables of the MRV, so for example:
             * [
             *     { brand: 'Toyota',     qty: 1, year: 1985 },
             *     { brand: 'Mercedes',   qty: 3, year: 1999 },
             *     { brand: 'Volkswagen', qty: 6, year: 2010 }
             * ]
             */
            rows.map(function(row) {
                /**
                 * Calculate here what you need to calculate, based on each row.
                 */
                total += row.qty; // TODO: delete this, just an example
            });

            /**
             * Update the parent form based on your needs
             */
            form.setValue('number_of_rows', rows.length); // TODO: delete this, just an example


        } catch (e) {
            /**
             * If you reach this point, then MRV is empty
             */
            console.log('No rows yet in MRV...', e)
        }
    };


    /**
     * field.change event is emitted by the form component
     */
    $rootScope.$on('field.change', c.onFieldChange);

    /**
     * Let's execute this also immediately, in case if we have some pre-defined rows in the MRV
     */
    c.onFieldChange();

};

 

Comments
Jasmin Ramirez
Mega Contributor

Hi,

Any insights on how you can do this on a target record? 

Community Alums
Not applicable

If the target record is opened within portal, I think it should work the same way.

However if target record is opened on platform, then it won't work as the Portal widget macro is not rendered there. Unfortunately I don't have any readymade solution for this use case, maybe you could experiment with a jelly-based macro on platform side, but I'm not sure if it would do the trick.

r_shukla
Tera Explorer

Great solution, thanks for sharing..!!

Sandesh9
Tera Guru

Hi Matyas,

 

How to get the row object when a row is removed from the mrvs? is there a way to do that?

 

Thanks,

Sandesh

Community Alums
Not applicable

Hi Sandesh,

 

to find the removed element: on each onChange event you'll need to make a local copy of the current value of the MRV, then compare the new value of the MRV to the previous one (to the local copy)

 

Any item which is missing from the new array, is the removed row.

Anubhav24
Mega Sage
Mega Sage

Hi @Community Alums ,

I have a similar query I need to populate a multi line text variable , with the value of the rows which are deleted.

Can you please guide me on this.

Version history
Last update:
‎07-20-2021 09:58 AM
Updated by:
Community Alums