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
Post a Comment