In my previous blog post Interactive Grid - Aggregate Validations, I have explained how we can do "Aggregate Validations" for Interactive Grid (IG) data using server side validations. Server side validations technique is useful for complex validations that may involve checking data from multiple tables or number of rows in IG are more than 50 etc. However, for simple validations, like the one defined in my previous blog post, we can achieve it using Java Script (JS) APIs available for IG, entirely on client side.
Let's consider the same example again. Budget planning, where you can allocate percentage for each category, like 10% for healthcare, 10% for education etc. Here, we need to implement a simple table level validation to ensure total allocation % does not exceed 100.
Important Note: When pagination style "Page" is chosen for IG, then only first 50 rows (or rows selected in "Rows Per Page") are loaded in the "modal". For pagination style "Scroll", initially 50 rows are loaded into the "modal" and subsequent rows are loaded as user scrolls down. So, if your IG has more than 50 rows, then choose pagination style as "Page" and choose "Rows Per Page" accordingly to ensure all rows are loaded into the model. You can also load all the rows into the model using model.fetchAll and it works for both the pagination styles.
However, if the number of rows in IG are more than 50, then, displaying all the rows in UI may not look good and could also have performance impact. Even if you use model.fetchAll to load all rows into the modal, it can still have performance impact. Below note is from APEX documentation.
Loading too much data onto the client can take a long time and cause the browser to become unresponsive.
So in these cases, I recommend to use technique I have explained in my previous blog post Interactive Grid - Aggregate Validations. Last, but not least, client side validations are good, but not sufficient. So, it's always recommended to have server side validations, irrespective of whether you have client side validations or not.
That's it. We are good to go. link to demo
What do you think about this approach? Do you have any other ideas to solve this problem? I welcome your feedback.
Thank you.
Update-1 on 12-APR-2020: Updated code to use model.save method to trigger ajax save, instead of page submit. Also updated some notes. Please refer comment from John Snyders below.
Let's consider the same example again. Budget planning, where you can allocate percentage for each category, like 10% for healthcare, 10% for education etc. Here, we need to implement a simple table level validation to ensure total allocation % does not exceed 100.
- To start with, create IG region on BLOG_BUDGET_PLANNING table and enable edit mode. Assume BLOG_BUDGET_PLANNING columns as PLAN_ID, PLAN_CATEGORY, PLAN_PERCENTAGE and Audit (Who) columns
- In IG > Attributes > Toolbar section, deselect "Save Button" option, so default IG "Save" button is not displayed.
- Next, create "SAVE" button which will trigger dynamic action and executes below JS code.
Dynamic Action JS Code.
var totalPercentage = 0; // get IG model. agg_val is interactive grid region "Static ID" var model = apex.region("agg_val").widget().interactiveGrid("getCurrentView").model; // loop through all the rows in model and calculate total allocation percentage model.forEach(function(record, index, id) { // PLAN_PERCENTAGE is column alias for "Allocation %" column var currPercentage = parseFloat(model.getValue(record, "PLAN_PERCENTAGE")), meta = model.getRecordMetadata(id); // ignore aggregated and deleted rows // we can use meta data of row to identify if the row is new or getting deleted etc. if (!isNaN(currPercentage) && !meta.deleted && !meta.agg) totalPercentage += currPercentage; }); //console.log("totalPercentage " + totalPercentage); // clear errors, if any apex.message.clearErrors(); if (totalPercentage <= 100) { /* Use below code if you want to submit the page */ /* apex.page.submit({ request: "SAVE", showWait: true }); */ // below code triggers IG AJAX Save and refreshes the IG region model.save(function() { apex.region("agg_val").refresh(); }); } else { // Error object, for single error errorDetails = { type: "error", location: ["page"], message: "Total Allocation should not exceed 100.", unsafe: false }; // show error apex.message.showErrors(errorDetails); }
Important Note: When pagination style "Page" is chosen for IG, then only first 50 rows (or rows selected in "Rows Per Page") are loaded in the "modal". For pagination style "Scroll", initially 50 rows are loaded into the "modal" and subsequent rows are loaded as user scrolls down. So, if your IG has more than 50 rows, then choose pagination style as "Page" and choose "Rows Per Page" accordingly to ensure all rows are loaded into the model. You can also load all the rows into the model using model.fetchAll and it works for both the pagination styles.
However, if the number of rows in IG are more than 50, then, displaying all the rows in UI may not look good and could also have performance impact. Even if you use model.fetchAll to load all rows into the modal, it can still have performance impact. Below note is from APEX documentation.
Loading too much data onto the client can take a long time and cause the browser to become unresponsive.
So in these cases, I recommend to use technique I have explained in my previous blog post Interactive Grid - Aggregate Validations. Last, but not least, client side validations are good, but not sufficient. So, it's always recommended to have server side validations, irrespective of whether you have client side validations or not.
That's it. We are good to go. link to demo
What do you think about this approach? Do you have any other ideas to solve this problem? I welcome your feedback.
Thank you.
Update-1 on 12-APR-2020: Updated code to use model.save method to trigger ajax save, instead of page submit. Also updated some notes. Please refer comment from John Snyders below.
Comments
It is possible to combine this with ajax save (rather than page submit) if you desire.