Important Update: Community URLs redirect issues are partially resolved. Learn More. .

cancel
Showing results for 
Search instead for 
Did you mean: 

Sub-Forms and Last Updated

TimothyScott1
Contributor III

I have noticed that saving new record entries to my sub-form does NOT update the 'Last Updated' field of my parent record.

How can I determine if a new sub-form entry has been made for the purposes of sending a notification?

I have tried using the Criteria 'Action Log' and operator 'Changed' but this seems to never evaluate to TRUE.

 

It seems the parent record is unaware of changes to the sub-form.

 

thank you!

26 REPLIES 26

You can create CR field in subform and feed the parent there. Otherwise, subform has no idea who the parent is, AFAIK.

Oh, CR = Cross Reference.  I didn't get the short hand.  Thanks for the idea.

 Not the best solution though, I still think it is somehow possible to get only via REST requests to the content, but would need some trials.

Bradley what you can do is in the parent application is create a custom object to store the record tracking id in a session variable (use sessionStorage.setItem('trackingId',getRecordId());).  Then in the sub-form create a custom object to read the session variable (use sessionStorage.getItem('trackingId');) and go from there.

 Advisory Consultant

That is elegant solution, only problem that you need to access parent record first and not form reports, but it is valid in most of the cases.

David,

 

This is exactly what I was looking for.  Thank you.

Ilya_Khen
Champion III

Great, thanks for sharing.

BradleyHanna
Contributor III

For those who are interested in this functionality, this is how you can trigger notifications when a record is added to a sub-form field.

 

First, create a custom object in the application containing the sub-form.  I will call this application "Tickets".

This custom object stores the record Id of the parent record for reference by the sub-form.  I use David Petty's answer in a Sys.Application.add_load function:  sessionStorage.setItem('trackingId', getRecordId()); .

 

Next, create a text field in the Tickets application and remember the field Id.  I'll call the text field "Log Changed".  Log Changed does not need to be in the layout, but it should be active.

 

In the sub-form add a custom object to the layout and create a JavaScript function run on page unload to ensure it runs on the SAVE AND CLOSE event.

 

function updateParentRecord() {
  // Get the parent record tracking number
  var trackingId = sessionStorage.getItem('trackingId');
  // The parent record field Log Changed will be referenced by its field Id #####
  var fieldId = #####;
  // Generate a unique value to ensure that the notification always evaluates true on changed
  var timestamp = new Date().valueOf();
  
  // Construct the body of the web request in JSON format, Id, Level Id, and Field Id are mandatory for a successful request
  // The timestamp value is included to update the Log Changed field
  var body = '{"Content":{"Id":' + trackingId + ',"LevelId": ###,"FieldContents":{"' + fieldId + '":{"Type": 1, "Value":"' + timestamp + '", "FieldId":' + fieldId + '}}}}'
  
  // Construct and send the web request
  var request = new XMLHttpRequest();
  request.open("PUT", "your url/platformapi/core/content");
  request.setRequestHeader("Accept", "application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
  request.setRequestHeader("Content-Type", "application/json");
  request.send(body);
 }

 

The web request updates the parent when the sub-form is closed.  Saving the parent record causes the Subscription Notification filter criteria to be evaluated.  Criteria "Log Changed = changed" triggers the notification.  This also works with a DDE.

 

I did have another question:

Should any considerations be made on garbage collection for that sessionStorage item?  Removing it on a page unload or dispose would remove it upon moving to the sub-form add new page, rendering it useless.

 

Thanks for all the responses that helped solve this problem.

The sessionStorage only lasts as-long-as the tab remains open.

 

If you want to do a clean up, you can call the follow:

sessionStorage.removeItem("trackingId");

 Advisory Consultant

Thanks so much for this!!

 

I got it working in our Dev environment but when I try it in Test it does nothing. There is no error but the parent fields remain blank. I've confirmed that it pulls the correct tracking ID and application name from the parent, that it grabs the correct information from the subform, and that the parent application field IDs are correct. Does anyone know of a reason why it would work in one environment but not the other?  Here is the code I put in the subform:

 

<script>
Sys.Application.add_load(function() {
 
  // Get the parent record tracking number
  var trackingId = sessionStorage.getItem('trackingId');
  // Generate a unique value to ensure that the notification always evaluates true on changed
  var timestamp = new Date().valueOf();
  // Get the application name
  var sName = sessionStorage.getItem('appId');
  // Get the environment piece of the URL
  var sInstance = window.location.hostname;

  // Hijack the save button to run our function on click
  $('#master_btnSave').attr('href',"#").removeAttr('onclick').unbind('click').prop("onclick", null);   

function grabData() {
   $('#master_btnSave').click(function(event){

      // Load field ID variables based on environment and application
      switch(sInstance) {
        case "attegrc-dev.cso.att.com":
       // Get comment and author text from subform   
       var recentComment = $('div[id*="f12789c"]').text().trim();
       var recentAuthorALL = JSON.parse($('input[id*="f12788c"]').val());
       var recentAuthorName = recentAuthorALL.text;
          switch(sName) {
            case "MRSP":
            var LevelId = 176;
            var ParentNewId = 19323;
            var ParentCommentId = 19305;
            var ParentAuthorId = 19307;
            break;
            case "MR":
                var LevelId = 172;
                var ParentNewId = 19330;
                var ParentCommentId = 19312;
                var ParentAuthorId = 19311;
            break;
          }
        break;
        case "attegrc-tst.cso.att.com":
       // Get comment and author text from subform   
       var recentComment = $('div[id*="f13264c"]').text().trim();
       console.log("comment is " + recentComment);
       var recentAuthorALL = JSON.parse($('input[id*="f13265c"]').val());
       var recentAuthorName = recentAuthorALL.text;
       console.log("author is " + recentAuthorName);
          switch(sName) {
            case "MRSP":
                var LevelId = 160;
                var ParentNewId = 15231;
                var ParentCommentId = 15216;
                var ParentAuthorId = 15218;
            break;
            case "MR":
                var LevelId = 162;
                var ParentNewId = 15232;
                var ParentCommentId = 15224;
                var ParentAuthorId = 15223;
            break;
          }
         break;
        case "attegrc.cso.att.com":
      // Get comment and author text from subform   
       var recentComment = $('div[id*="f12789c"]').text().trim();
       var recentAuthorALL = JSON.parse($('input[id*="f12788c"]').val());
       var recentAuthorName = recentAuthorALL.text;
          switch(sName) {
            case "MRSP":
                var LevelId = 176;
                var ParentNewId = 19323;
                var ParentCommentId = 19305;
                var ParentAuthorId = 19307;
            break;
            case "MR":
                var LevelId = 172;
                var ParentNewId = 19330;
                var ParentCommentId = 19312;
                var ParentAuthorId = 19311;
            break;
          }
        break;
        }       

 // Construct the body of the web request in JSON format
 var body = '{"Content":{"Id":"' + trackingId + '", "LevelId":' + LevelId + ',"FieldContents":{"' + ParentNewId + '":{"Type":1, "Value":"' + timestamp + '", "FieldId":' + ParentNewId + '},"' + ParentCommentId + '":{"Type":1, "Value":"' + recentComment + '", "FieldId":' + ParentCommentId + '},"' + ParentAuthorId + '":{"Type":1, "Value":"' + recentAuthorName + '", "FieldId":' + ParentAuthorId + '}}}}'
 console.log("body is " + body);
 // Construct and send the web request
 var request = new XMLHttpRequest();
 var requestURL = 'https://' + sInstance + '/ATTeGRC/platformapi/core/content'
 console.log("URL is " + requestURL);
 request.open("PUT", requestURL);
 request.setRequestHeader("Accept", "application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
 request.setRequestHeader("Content-Type", "application/json");
 request.send(body);
 __doPostBack('master$btnSave','');
    });
  };

  grabData();
});

</script>