0

I've created a JavaScript OnSave event that parses through a "Sales Quota Distribution" entity grid within an "Opportunity" entity form, and checks for duplicates in the "Resource" field of the "Sales Quota Distribution" grid. When there is a duplicate, a warning message will appear. This is working, but I'd like to be able to append the OnSave event to not allow the user to save the form if there are no duplicate resources. How can I do this?

Below is my current code:

function GetTotalResourceCount(executionContext) {
    console.log("function started");
    var execContext = executionContext;
    var formContext = executionContext.getFormContext();
    var resourceyescount = 0;
    try {
        var gridCtx = formContext._gridControl;
        var grid = gridCtx.getGrid();
        var allRows = grid.getRows();
        //get rows - use the getControl method and pass the grid name.
        //var gridContext = formContext.getControl("s_qd");
        //        if (formContext.getGrid().getTotalRecordCount() == 0) {
        //           setTimeout(function () { GetTotalResourceCount(execContext); }, 2000);
        //           return;
        //       }
        var duplicatesFound = 0;
        //loop through rows and get the attribute collection
        allRows.forEach(function (row, rowIndex) {
            var thisRow = row.getData().entity;
            var thisRowId = thisRow.getId();
var thisResource = "";
var thisResourceName = "";
var thisResourceID = "";
            console.log("this row id=" + thisRowId);
            var thisAttributeColl = row.getData().entity.attributes;
            thisAttributeColl.forEach(function (thisAttribute, attrIndex) {
                var msg = "";
                if (thisAttribute.getName() == "new_resource") {
                    thisResource = thisAttribute.getValue();
thisResourceID = thisResource[0].id;
thisResourceName = thisResource[0].name;
                }
            });

            // Loop through every row and find one with
            // thatresource == thisResource &&
            // thatrow ID != thisRowId
            var allRows2 = formContext.getGrid().getRows();
            //loop through rows and get the attribute collection
            allRows2.forEach(function (row, rowIndex) {
                var thatRow = row.getData().entity;
                var thatRowId = thatRow.getId();
                var thatAttributeColl = row.getData().entity.attributes;
var thatResource = "";
var thatResourceName = "";
var thatResourceID = "";
                thatAttributeColl.forEach(function (thatAttribute, attrIndex) {
                    if (thatAttribute.getName() == "new_resource") {
                        thatResource = thatAttribute.getValue();
thatResourceID = thatResource[0].id;
thatResourceName = thatResource[0].name;
                        if (thatResourceID == thisResourceID && thatRowId != thisRowId) {
                            duplicatesFound++;
                            var msg = "Duplicate resource " + thatResource;
                        }
                    }
                });
            });
        });

        if (duplicatesFound > 0) {
            console.log("duplicate found");
            Xrm.Utility.alertDialog("WARNING: There are duplicate resources in the Sales Quota Distribution grid.");
        }
    } catch (err) {
        console.log('Error occurred :' + err)
    }
}

Any help would be greatly appreciated. Thanks! enter image description here

Tim G
  • 147
  • 4
  • 11

2 Answers2

0

What you need is preventDefault (Client API reference) Few example links here,

Javascript – Prevent Save

Cancelling save event based on the result of async operation

Try below code, I have added just 2 lines var saveEvent = executionContext.getEventArgs();saveEvent.preventDefault();

Assuming your function GetTotalResourceCount(executionContext) is running onSave Event.

function GetTotalResourceCount(executionContext) {
    console.log("function started");
    var execContext = executionContext;
    var formContext = executionContext.getFormContext();
    var resourceyescount = 0;
    try {
        var gridCtx = formContext._gridControl;
        var grid = gridCtx.getGrid();
        var allRows = grid.getRows();
        //get rows - use the getControl method and pass the grid name.
        //var gridContext = formContext.getControl("s_qd");
        //        if (formContext.getGrid().getTotalRecordCount() == 0) {
        //           setTimeout(function () { GetTotalResourceCount(execContext); }, 2000);
        //           return;
        //       }
        var duplicatesFound = 0;
        //loop through rows and get the attribute collection
        allRows.forEach(function (row, rowIndex) {
            var thisRow = row.getData().entity;
            var thisRowId = thisRow.getId();
var thisResource = "";
var thisResourceName = "";
var thisResourceID = "";
            console.log("this row id=" + thisRowId);
            var thisAttributeColl = row.getData().entity.attributes;
            thisAttributeColl.forEach(function (thisAttribute, attrIndex) {
                var msg = "";
                if (thisAttribute.getName() == "new_resource") {
                    thisResource = thisAttribute.getValue();
thisResourceID = thisResource[0].id;
thisResourceName = thisResource[0].name;
                }
            });

            // Loop through every row and find one with
            // thatresource == thisResource &&
            // thatrow ID != thisRowId
            var allRows2 = formContext.getGrid().getRows();
            //loop through rows and get the attribute collection
            allRows2.forEach(function (row, rowIndex) {
                var thatRow = row.getData().entity;
                var thatRowId = thatRow.getId();
                var thatAttributeColl = row.getData().entity.attributes;
var thatResource = "";
var thatResourceName = "";
var thatResourceID = "";
                thatAttributeColl.forEach(function (thatAttribute, attrIndex) {
                    if (thatAttribute.getName() == "new_resource") {
                        thatResource = thatAttribute.getValue();
thatResourceID = thatResource[0].id;
thatResourceName = thatResource[0].name;
                        if (thatResourceID == thisResourceID && thatRowId != thisRowId) {
                            duplicatesFound++;
                            var msg = "Duplicate resource " + thatResource;
                        }
                    }
                });
            });
        });

        if (duplicatesFound > 0) {
            console.log("duplicate found");
            Xrm.Utility.alertDialog("WARNING: There are duplicate resources in the Sales Quota Distribution grid.");
             var saveEvent = executionContext.getEventArgs();
             saveEvent.preventDefault();
        }
    } catch (err) {
        console.log('Error occurred :' + err)
    }
}
colinD
  • 1,641
  • 1
  • 20
  • 22
AnkUser
  • 5,421
  • 2
  • 9
  • 25
  • Thank you. Unfortunately adding those two lines of code did not work. The code still runs as it did before, but the form still saves. Any ideas? – Tim G Mar 26 '20 at 21:25
  • Can you try replacing `formContext.getEventArgs();` by `executionContext.getEventArgs();`? I think the function is not called on the right object, it should be `executionContext`, see [here](https://learn.microsoft.com/en-us/powerapps/developer/model-driven-apps/clientapi/reference/executioncontext/geteventargs) – colinD Mar 27 '20 at 08:16
  • Thank you! This worked. I do have one more question: Is there a way I can allow the user to save again once the duplicate has been removed from the grid? For example, I'd like to have something like: if (duplicatesFound > 0) { console.log("duplicate found"); Xrm.Utility.alertDialog("WARNING: There are duplicate resources in the Sales Quota Distribution grid."); var saveEvent = executionContext.getEventArgs(); saveEvent.preventDefault(); } else { (code to allow user to save goes here) } – Tim G Apr 02 '20 at 03:42
  • Could you please mark this as solved first asked question is solved. – AnkUser Apr 02 '20 at 07:14
0

You can also use the setNotification method on one of the controls. This will prevent the form from being saved.

From the documentation:

Setting an error notification on a control will block the form from saving.

So like:

formContext.getControl('your_attributename').setNotification('This will be displayed', 'optional id');
colinD
  • 1,641
  • 1
  • 20
  • 22
  • thank you. I added the following code inside my "if (duplicatesFound > 0)" statement: formContext.getControl('new_resource').setNotification('A duplicate resource was added.', 'optional id'); Unfortunately, no message appeared when I added a duplicate resource and I was still able to save the form. Am I adding this line of code in the wrong place? – Tim G Mar 26 '20 at 21:31
  • This function is called on save of the form? And the field `new_resource` is on the form? – colinD Mar 26 '20 at 22:34
  • Yes, the function is called on save of the form. The "new_resource" field is in the "Sales Quota Distribution" entity grid, which is in the Opportunity entity form. – Tim G Mar 27 '20 at 04:22
  • For reference, I've just added a screenshot to my original post of the Sales Quota Distribution grid inside the Opportunity form. – Tim G Mar 27 '20 at 04:25
  • Ok so I think that's why. It only works if the field in on the main form I guess. – colinD Mar 27 '20 at 08:12