Setting Reference Field Programatically

  • 1
  • Problem
  • Updated 5 years ago
  • Solved
I am having difficulty setting related fields programatically within a popup.

Use Case:
  • We have a 'Relationship' object which needs to support a reference to one of three other types, specifically 'Team Member', 'Organisation', or 'Person'.
  • Given my understanding is that custom objects do not support this type of dynamic/polymorphic relationship, our design approach is to have a dummy field called 'Search Text', which is rendered in a Skuid field editor using a dynamic render snippet.
  • As various events are triggered on the dummy field, the appropriate Id values for related records are set on the underlying row. For example: if an organisation is selected in the 'Search Text' field, the dynamic rendering code will set like so: 
params.row.cloupra__To_Organisation__c = ui.item.id;
params.row.cloupra__To_Organisation__r = {Id: ui.item.id, Name: ui.item.name};
  • The actual save is triggered by the "Save/Cancel" button on the popup that contains the field editor. I have intercepted this call, and the object passed to skuid.model.save contains the (apparently) correct values.
Without a browser refresh, this seems to work, however no data persists in SF. I'm four days into this, and so I would greatly appreciate a fresh insight.

Kind Regards,
Dan Arnison
Photo of Dan A

Dan A

  • 314 Points 250 badge 2x thumb

Posted 5 years ago

  • 1
Photo of Zach McElrath

Zach McElrath, Employee

  • 49,056 Points 20k badge 2x thumb
Hi Dan,

Can you post your full code snippet?

In order for Skuid to "know" about changes that you've made to data, you need to use Skuid's API methods to actually make changes to data rows. The principal method that is essential to use here is model.updateRow(row,field,value). See lines 23-27 in Example 1 in our skuid.model tutorial.

updateRow does several things:

1. Checks whether the field you're trying to update IS in fact updateable given the user's permissions on that field --- if not, the update request is ignored.
2. Makes an entry in internal "changes" and "originals" objects to keep track --- this "changes" object is what Skuid uses during model.save operations to determine what to tell the server about. If there's nothing in Skuid's changes object, then Skuid won't even go to the server at all.
3. Modifies the row object stored in model.data --- which is what you are handed via params.row, or using Model API methods such as model.getRowById(rowId), or model.data[0], model.getFirstRow(), etc. 

There's a couple of variants on updateRow that are designed for bulk modifications, e.g. trying to update multiple fields at once on a single row, or for trying to update multiple rows at once.

So you can also write something like:

model.updateRow(row,{
   'Foo__c': 'Bar',
   'Hello__c':'World'
});

and Skuid will update the "Foo__c" field's value to be "Bar", and the "Hello__c" field's value to be "World".

So, now to your question about REFERENCE fields. If you are going to be immediately doing a Save after running updateRow, then you only need to set the foreign key field in order for the update to be applied server-side, e.g.

params.model.updateRow(params.row,'cloupra__To_Organisation__c',ui.item.id);
params.model.save();

Once the Save operation is successful, if you have the Name field on the related record (e.g. cloupra__To_Organization__r) in your Model, Skuid will query this field, and you'll see the Name field's value as well on your row, e.g. your Relationship row will, after this save is run, have the following:

// Get our updated Relationship row
var relationshipModel = skuid.model.getModel('Relationships');
var relationshipRow = relationshipModel.getRowById(params.row.Id);
console.log(relationshipRow);
// ===>
{
   cloupra__To_Organisation__c: <ID>,
   cloupra__To_Organization__r: <object> { Name: "Acme Inc" }
}

Now, backing up a little bit:

If you had NOT wanted to run model.save() right away, and had been wanting some other piece of the User interface to show, pre-save, client-side, the related field's Name field value "Acme Inc", then you should also have also populated the foreign key name:

params.model.updateRow(params.row,{
   cloupra__To_Organisation__c: ui.item.id,
   cloupra__To_Organisation__r: {Id: ui.item.id, Name: ui.item.name}
});

The benefit of this is passing in an object for cloupra__To_Organisation__r is that Skuid will use this data to display the Name field value of the related Organization where needed. The simple act of doing an updateRow, however, will not always cause the UI to change --- events such as model.save() and model.updateData() will force bound UI components to rerender themselves, but there are ways to trigger this re-rendering before you've done a save when needed, for instance if you have a Table or Field Editor that is displaying this data, you can tell these Components to re-render themselves or to re-render relevant parts of themselves.

Photo of Dan A

Dan A

  • 314 Points 250 badge 2x thumb
Hi Zach,

Perfect... that works like a treat.

Kind Regards,
Dan Arnison