Javascript: Create new row and set Lookup field to reference an unsaved object (SKUID Temp ID, not Salesforce Id)?

  • 1
  • Question
  • Updated 6 hours ago
  • Answered
I have a model on my page with a row that is not yet saved to Salesforce, so it has a SKUID Temp ID pending a save to the database.

I'm trying to create a new row in a related model as follows (example javascript):
relatedModel.createRow({doAppend:true, additionalConditions:[
        {field: 'ParentLookup__c', value: skuidTempIdFromMainObjectsModel}
    ]}
);
The skuidTempIdFromMainObjectsModel is properly populated with the SKUID Temp ID of the parent object, but it would appear when I create a new row this way, the ParentLookup__c field on the newly created row is empty (it doesn't pass the skuid temp ID over)

In the SKUID editor you are able to create a new row and pass skuid temp IDs over and once the models save everything works properly to associate the items together. How can this be accomplished when creating new rows via javascript?

Thanks!

Photo of Mark L

Mark L

  • 2,116 Points 2k badge 2x thumb

Posted 2 months ago

  • 1
Photo of Mark L

Mark L

  • 2,116 Points 2k badge 2x thumb
Ah it looks like on further inspection the row does get created with the skuid temp ID in the lookup field.

I guess my only question then is: is this the right approach? When I go to save will everything associate properly?
Photo of Mark L

Mark L

  • 2,116 Points 2k badge 2x thumb
It looks like this is indeed not the right approach, as when you save you get an error "Invalid Reference Id"

How do I go about setting the Lookup field on the child objects I create in Javascript with the temporary ID of the parent in such a way so that when these save they relate properly?
Photo of Mark L

Mark L

  • 2,116 Points 2k badge 2x thumb
I've found a workaround to make this happen. I've taken the approach of overwriting the "ParentLookup__c" field in all of the child models with the ID of the Parent object in the UI editor prior to saving all my models. (Model: Update Rows - All Rows : ParentLookup__c = Field From Another Model: ParentModel:Id)

Setting the lookups this way in the UI Editor causes the new rows to save with the proper ID associated. I just wish there were a more straightforward way to achieve this when creating a new row / associating a Lookup to an unsaved parent in javascript.
(Edited)
Photo of Mark L

Mark L

  • 2,116 Points 2k badge 2x thumb
Still very curious as to how to make this happen without having to find an indirect and not always applicable workaround using the SKUID Editor interface.

Does anyone have any idea if it is possible / how to assign in Javascript a lookup relationship between 2 objects that have not yet saved to the database in such a way that it will save properly when the models are saved together?

Currently it seems if you just set the Lookup of the child to the ID of the parent in Javascript, it will set it as the SKUID temporary Id, and when you try to save  it will give an invalid ID error thinking that the SKUID Temporary ID should be the Salesforce ID rather than intelligently relating the objects together as it does when setting unsaved object lookups in the SKUID Editor.
Photo of Anna Wiersema

Anna Wiersema, Official Rep

  • 11,754 Points 10k badge 2x thumb
Hi Mark, glad you were able to find a workaround for now.

In general, when creating new records and their children this is what we recommend:
  1. Have the child model use "field from another model" condition to be linked to the first model. (Eg. If you are creating an Account and Contacts related to it, set up a condition on the New Contacts model where AccountId = field from another model > New Account Model > Id).
  2. When saving, you can configure a button to run multiple actions via the action framework.  If your parent model (e.g. Account) is listed before your child model (e.g. Contacts) in the list, you should not encounter any errors since it will be saved before the other model.  If you do run into difficulties, you can add two discrete actions, one to Save the parent record, and, if this action succeeds another to save the child record.
Does this sound like what you're trying to do? Let me know if you have additional questions about this.


Additional information:
(Edited)
Photo of Mark L

Mark L

  • 2,116 Points 2k badge 2x thumb
Hi Anna,

Thanks for the information but this is not helpful for my situation. The problem occurs when you are working with rows in javascript and setting the lookup relationship in javascript.

For instance:

//parentModel is unsaved (the row has a skuid temporary ID)
//parentRow is first row in model (unsaved, has a SKUID temporary ID)
childModel.createRow({doAppend: true, additionalConditions: [
{field: 'LookupField1__c', value: parentModel.getFieldValue(parentRow,'Id',true)},
]
});
The child row will have its lookup field set to the SKUID temporary ID of the parent object because the parent object remains unsaved. In the UI editor this sort of thing would be accomplished via "Field from another model" when creating the child row, but in Javascript it seems the only way to set the lookup is to just set the field with the SKUID temporary Id in the manner outlined above.

Now if you save the child model, you get an error that the ID on LookupField1__c is invalid. If this was set in the UI editor via "Field from another model" you wouldn't get this error.

There really needs to be a way to set these lookup relationships to unsaved rows in javascript similar to the way to do it in the UI editor, otherwise operations where you are relating rows together that are too complex for the UI editor and require javascript are limited in that the parent row you are trying to relate needs to be saved prior to associating the lookup, which is in many cases not something that you'd want to do; you want to only save everything together / error everything together like you can do in the UI editor to prevent bad data saving to the system.

The only possible workaround I've found is after creating the rows in javascript and prior to saving the models go through and update all rows of the child model to have the Lookup be a "Field from another model" specified in the UI editor (must be done outside of javascript). This workaround however only works if you have a static setup where all child rows lookup to the same parent object and you can clearly set all lookup relationships with the same parent row. It does not work for more complex setups where you are trying to set lookups on children for multiple different parents each with their own IDs and lookup relationships.

We have a project we're working on right now where we're trying to set lookups for multiple parent/child relationships that we can't do in SKUID because of this limitation and instead will have to resort to other more convoluted resources to set this up such as APEX or Salesforce Flows / Processes.

(Edited)
Photo of Anna Wiersema

Anna Wiersema, Official Rep

  • 11,754 Points 10k badge 2x thumb
Hi Mark, I agree it sounds like there should be a way to accomplish this. We'll do some research and get back to you.

In the meantime, can you share more about your specific use case?  It sounds like you may be trying to create multiple parent records and their children at the same time.  If you can share more about the specifics, it will help us know how to direct you more effectively.
Photo of Mark L

Mark L

  • 2,116 Points 2k badge 2x thumb
Thanks!

Further example:

I have just created a list of parent objects (not yet saved). For each parent object in that list I want to create any number different child objects (of a different object type) and associate a lookup relationship between each parent object in the list and its child objects via a lookup relationship on the child object to the parent object. I then want to do a save all at once, erroring / rolling back changes if anything fails. Since I'm running through loops here the only way I can see to do this is in javascript; however setting lookup relationships in javascript between unsaved objects that have SKUID temporary IDs doesn't work the same way it would in the UI editor via "field from another model", when saving it will give an invalid ID on lookup field error.
Photo of Anna Wiersema

Anna Wiersema, Official Rep

  • 11,754 Points 10k badge 2x thumb
Hi Mark, thanks for the details of your use case. Here's what we recommend:
  1. Set up your parent and child object models declaratively in Skuid using the process outlined above with the field from another model condition on the lookup field.
  2. Then, you can create the new records and their children via the action framework or JS.  You must save the parents and the children at the same time. In the Action Framework you can also handle which messages to show and which actions to run if there are errors with the save.
Here's more resources on how to accomplish this:
Photo of Mark L

Mark L

  • 2,116 Points 2k badge 2x thumb
Hi Anna,

I'm not sure that I follow here. How do I loop through the parent objects and create a child object for each parent object (each related specifically to its own parent object) in the UI editor (without javascript)? There doesn't appear to be a way to do this.
Photo of Anna Wiersema

Anna Wiersema, Official Rep

  • 11,754 Points 10k badge 2x thumb
Hi Mark, based on our understanding of what you're trying to accomplish, it sounds like these specific model APIs may be helpful:
Happy building!
Photo of Mark L

Mark L

  • 2,116 Points 2k badge 2x thumb
Hi Anna,

So you're saying that if I use skuid.model.save(ArrayOfBothModelsToSaveSimultaneously) it won't give the invalid ID error?

I've run through a test of this and it appears to work!!

var params = arguments[0], $ = skuid.$;
var am = skuid.model.getModel('AccountModel');
var cm = skuid.model.getModel('ContactModel');
var models = [];
models.push(am);
models.push(cm);
$.when(am.createRow({doAppend: true, additionalConditions: [
{field: 'Name', value: 'TEMPVARTESTACCOUNT'}
]
})).done(function(){
    var amRow = am.getFirstRow();
    
$.when(cm.createRow({doAppend: true, additionalConditions: [
    {field: 'LastName', value: 'TEMPVARTESTER'},
    {field: 'AccountId', value: am.getFieldValue(amRow,'Id',true)}
    ]
    })).done(function(){
        
    skuid.model.save(models, {rollbackOnAnyError: true,callback: function(result){
        console.log('SAVE RESULTS:');
        console.log(result); //Success!!
    }});
    });
});

It also appears that if I run an action sequence (UI editor) based save on both models simultaneously that is working as well. This is very strange though because I was using an action sequence based save on all models simultaneously before when I first created this forum thread and it was giving me the invalid Id error; now that I try coding it out in my test example it seems to not be having that problem. Very peculiar. It's been a while since I had this error in my original code and I've since reworked it using a different strategy for saving / relating items. I'll let you know if I can reproduce my original issue as we're coding our new project up and do some more testing around it, otherwise it appears this strategy works! Thanks!

Photo of Anna Wiersema

Anna Wiersema, Official Rep

  • 11,754 Points 10k badge 2x thumb
Thanks for the update, Mark, sounds good.