Skip to main content

Save/process all selected rows on Grid

O

On rare cases I want to process selected rows in grid even if they were not changed. And I want to process them through standard grid handler, not via customized AJAX callback. Just like you would changed the rows and pressed Save.


I would like to add a button Save Selected to the grid after the Save button. But not to all grids. To achieve this you can use CSS classes on the grid. In JavaScript I will check if grid has the SAVE_SELECTED class and only then I will add the button. No need to hardcode static id.

Lets create a table first and a simple trigger just for demo purposes too verify that selected rows were actually changed:

CREATE TABLE settings2 (
    setting_name        VARCHAR2(30)    CONSTRAINT nn_settings2_id  NOT NULL,
    setting_value       VARCHAR2(256),
    --
    is_numeric          CHAR(1),
    is_date             CHAR(1),
    --
    updated_by          VARCHAR2(30),
    updated_at          DATE,
    --
    CONSTRAINT pk_settings2
        PRIMARY KEY (setting_name),
    --
    CONSTRAINT ch_settings2_is_active
        CHECK ((is_numeric = 'Y' AND is_date IS NULL) OR is_numeric IS NULL),
    --
    CONSTRAINT ch_settings2_is_date
        CHECK ((is_date = 'Y' AND is_numeric IS NULL) OR is_date IS NULL)
)
STORAGE (BUFFER_POOL KEEP);
CREATE OR REPLACE TRIGGER settings2__
FOR UPDATE OR INSERT OR DELETE ON settings2
COMPOUND TRIGGER

    BEFORE EACH ROW IS
    BEGIN
        :NEW.updated_by     := COALESCE(APEX_APPLICATION.G_USER, USER);
        :NEW.updated_at     := SYSDATE;
    END BEFORE EACH ROW;

END;
/


Select few rows you would like to process...

...and hit the Save Selected button. You should see something like this. A proof which rows were processed.


Solution

Check this code:

    // add action to save all selected and changed rows
    if ($region.hasClass('SAVE_SELECTED')) {
        col_name = $region.attr('class').match(/SAVE_COL_(?[^\s]*)/).groups.name;     // fake column
        actions.add({
            name    : 'SAVE_SELECTED',
            action  : function(event, element) {
                var region_id   = event.delegateTarget.id.replace('_ig', '');
                var grid        = apex.region(region_id).widget();
                var model       = grid.interactiveGrid('getViews', 'grid').model;
                var gridview    = grid.interactiveGrid('getViews').grid;
                var selected    = grid.interactiveGrid('getViews').grid.getSelectedRecords();
                var id;
                var changed = [];
                //
                for (var i = 0; i < selected.length; i++ ) {
                    id = gridview.model.getRecordId(selected[i]);
                    changed.push(id);
                };
                //
                model.forEach(function(r) {
                    for (var i = 0; i < changed.length; i++ ) {
                        if (changed[i] == gridview.model.getRecordId(r)) {
                            try {
                                model.setValue(r, col_name, model.getValue(r, col_name) + ' ');  // fake change
                            }
                            catch(err) {  // deleted rows cant be changed
                            }
                        }
                    }
                });
                //
                grid.interactiveGrid('getActions').invoke('save');

                // refresh grid after save
                //grid.interactiveGrid('getViews', 'grid').model.clearChanges();
                //grid.interactiveGrid('getActions').invoke('refresh');
                grid.interactiveGrid('getCurrentView').model.fetch();
            }
        });
        //
        action2.controls.push({
            type        : 'BUTTON',
            label       : 'Save Selected',
            id          : 'save_all_rows',
            icon        : '',
            action      : 'SAVE_SELECTED',
        });
    }


Remember the "..." from previous article? Thats a great place where to put this code.


How it works

The secret is to actually change the selected row (preferrably not visible column) and then submit the grid. User wont see changes, but they are there. To specify which column can be changed we will use another CSS class. For updated_by column you would add SAVE_COL_UPDATED_BY class, for setting_name it would be SAVE_COL_SETTING_NAME... And you also need to add the SAVE_SELECTED class to activate this feature.


For some special cases you might want to save/process all rows in grid. The code for that is very similar, you can certainly figure this out.

Do you know a better way how to do this?


Comments