web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

Community site session details

Community site session details

Session Id :
Power Platform Community / Forums / Power Apps / Model-driven App On-Sa...
Power Apps
Unanswered

Model-driven App On-Save Event

(0) ShareShare
ReportReport
Posted on by 14

Hi;

I am trying to create a unique identifier for each record that is saved using a form in a model-driven app. The identifier should be generated by combining values from three other fields in the form based on specific criteria. To achieve this, I have implemented a JavaScript function that will run when the form is saved. 

The form contains two choice fields, one date field, and a read-only simple text field where the generated ID should appear after saving the form. The JavaScript function uses the first two letters from choice field 1, assigns another letter based on the year selected in the date field, and assigns a sequential number with an increment of 1 based on the selection from choice field 2. I added the function to the on save event handler on the main form. However, the function is currently returning an empty result when the form is saved, and I'm unable to identify the cause of the issue. What possibly can be wrong here? and is there another way to achieve this logic?

I have the same question (0)
  • Drew Poggemann Profile Picture
    9,287 Most Valuable Professional on at

    Hi @Ghassanaq ,

     

    I am not sure why your JS is not working but you had asked another way to accomplish...


    One option would be to use a Power Automate Flow to set this information based on an update to the record for any of the fields you identified (date, text, choice columns).  This way it would update the value of your combined field even if someone updates the values of the fields through an import, a different form, etc.  This is not real-time though as it would kickoff on the update of the record and happen in the background asynchronously.

     

  • Ghassanaq Profile Picture
    14 on at

    Thanks dear for providing the solution, but I think I would prefer something in real time. But as I understand from your reply that JavaScript on save should work as a solution if done properly.

  • Guido Preite Profile Picture
    1,488 Super User 2024 Season 1 on at

    if you can post the code of this JS function can see if something is not correct.

    However I suggest to use a plugin (c# code) to implement this requirement

  • Ethan_009 Profile Picture
    4,838 Moderator on at

    Hi @Ghassanaq ,

     

    You can run Plugins in real-time by keeping it synchronous and using Pre-Operation.
    You can configure the sequence and validate that in Plugin

    If everything ok then create record else throw error.

     

    Note: If JS is disabled then your code will never run, this will impact your Business process.

     

    Hope this helps

  • Ghassanaq Profile Picture
    14 on at

    Thanks for reply, I will look into the plugin solution. 

    Below is the code that I am trying to implement: 

     
    function generatereqnum() {
     var department = Xrm.Page.getAttribute("cr8b8_department").getValue();
     var requestdate = Xrm.Page.getAttribute("cr8b8_requestdate").getValue();
     var requesttype = Xrm.Page.getAttribute("cr8b8_requesttype").getValue();
     
     if (!department || !requestdate || !requesttype) {
     return;
     }
     
     var departmentCode = "";
     var yearCode = "";
     var sequentialNumber = "";
     var reqnum = "";
     
     switch (department) {
     case "Call Center":
     departmentCode = "CC";
     break;
     case "Human Resources":
     departmentCode = "HR";
     break;
     case "Management":
     departmentCode = "MT";
     break;
     default:
     return;
     }
     
     var year = requestdate.getFullYear();
     var yearCodeMap = {
     2021: "A",
     2022: "B",
     2023: "C",
     2024: "D",
     2025: "E",
     };
     
     if (!yearCodeMap.hasOwnProperty(year)) {
     return;
     }
     
     yearCode = yearCodeMap[year];
     
     switch (requesttype) {
     case "ICT":
     sequentialNumber = generateSequentialNumber("0001-0999", function (result) {
     if (result) {
     reqnum = departmentCode + yearCode + result;
     Xrm.Page.getAttribute("cr8b8_reqnum").setValue(reqnum);
     }
     });
     break;
     case "Furniture":
     sequentialNumber = generateSequentialNumber("1000-1999", function (result) {
     if (result) {
     reqnum = departmentCode + yearCode + result;
     Xrm.Page.getAttribute("cr8b8_reqnum").setValue(reqnum);
     }
     });
     break;
     case "Others":
     sequentialNumber = generateSequentialNumber("2000-2999", function (result) {
     if (result) {
     reqnum = departmentCode + yearCode + result;
     Xrm.Page.getAttribute("cr8b8_reqnum").setValue(reqnum);
     }
     });
     break;
     default:
     return;
     }
     }
     
     function generateSequentialNumber(range, callback) {
     var sequentialNumber = "";
     var numbers = range.split("-");
     var start = parseInt(numbers[0]);
     var end = parseInt(numbers[1]);
     var fetchXml =
     '<fetch count="1" aggregate="true">' +
     '<entity name="cr8b8_requests">' +
     '<attribute name="cr8b8_sequentialnumber" aggregate="max" as="highestSequentialNumber" />' +
     '<filter>' +
     '<condition attribute="cr8b8_requesttype" operator="eq" value="' +
     Xrm.Page.getAttribute("cr8b8_requesttype").getValue() +
     '" />' +
     '<condition attribute="cr8b8_requestdate" operator="on-or-after" value="' +
     Xrm.Page.getAttribute("cr8b8_requestdate").getValue().toISOString() +
     '" />' +
     "</filter>" +
     "</entity>" +
     "</fetch>";
     
     Xrm.WebApi.retrieveMultipleRecords("cr8b8_requests", "?fetchXml=" + fetchXml).then(
     function success(result) {
     var maxSeqNumber = result.entities.length > 0 ? result.entities[0]["highestSequentialNumber"].value : start - 1;
     for (var i = start; i <= end; i++) {
     if (i > maxSeqNumber) {
     sequentialNumber = i.toString().padStart(4, "0");
     callback(sequentialNumber);
     break;
     }
     }
     },
     function (error) {
     console.log(error.message);
     callback("");
     }
     );
     
     return sequentialNumber;
     }
     

     

  • Guido Preite Profile Picture
    1,488 Super User 2024 Season 1 on at

    the main problem with your code is that Xrm.WebApi.retrieveMultipleRecords is asynchronous, meaning that the rest of your code will finish to execute (so your whole save event) before the results are returned (this probably is why you get an empty).

    You can switch to sync code (using jquery for example) but I strongly suggest to use a plugin.

  • Ethan_009 Profile Picture
    4,838 Moderator on at

    Hi @Ghassanaq ,

     

    What's not correct in your code,

    1. Don't use Xrm.Page -> instead use formContext (check documentation or blog online)

    2. Process flow isn't stable, as 'Xrm.WebApi.retrieveMultipleRecords' is an async call, you need to handle the output accordingly.

     

    To Note: Scopes and Promises 

     

    How to handle: 

    1. In success call of 'Xrm.WebApi.retrieveMultipleRecords' you can call another function and pass details so chain of process is maintained.

    2. If you want different approach then you can use async - await calls in your code.

     

    Hope this helps

  • Federico Pelliccia Profile Picture
    143 on at

    I could remember wrong, but even if you use async/await in your save function, it doesn't work.
    If they doesn't want use plugins, best option for me is to load generateSequentialNumber with the onLoad method, saving his value on a global variable and updating it with an addOnChange on Field 2.
    So when the Save start, the variable is already saved and updated

  • Ethan_009 Profile Picture
    4,838 Moderator on at

    Yes @FPelliccia  that's correct and better to store it and later saving the form. 👍🏻

  • Ghassanaq Profile Picture
    14 on at

    Thanks Ethan, I tried an async/await and also didnt work

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Forum hierarchy changes are complete!

In our never-ending quest to improve we are simplifying the forum hierarchy…

Ajay Kumar Gannamaneni – Community Spotlight

We are honored to recognize Ajay Kumar Gannamaneni as our Community Spotlight for December…

Leaderboard > Power Apps

#1
WarrenBelz Profile Picture

WarrenBelz 717 Most Valuable Professional

#2
Michael E. Gernaey Profile Picture

Michael E. Gernaey 329 Super User 2025 Season 2

#3
Power Platform 1919 Profile Picture

Power Platform 1919 268

Last 30 days Overall leaderboard