How do I refresh (updateData) a model with a dependent modelmerge condition?

  • 1
  • Question
  • Updated 5 years ago
I have a model with a modelmerge condition that I need to dynamically refresh (call updateData) when the underlying dependent model use in the modelmerge condition has changed. I've tried to refresh the dependent model and then updateData on the parent model with no success, have tried deactivating and reactivating conditions and still no luck,

I can't get the condition merge values to change once they've been set?Is there a way to force a model's modelmerge condition to re-query/evaluate itself?

Have attached sample models (not a whole page) so hopefully this make sense.



<model id="EntitySubscriptionFollowers" limit="999" query="true" createrowifnonefound="false" sobject="EntitySubscription">
<fields>
<field id="SubscriberId"/>
<field id="Subscriber.Name"/>
<field id="ParentId"/>
<field id="Parent.Name"/>
</fields>
<conditions>
<condition type="param" value="id" field="ParentId" operator="=" userinfotype="userid" enclosevalueinquotes="true"/>
</conditions>
</model>
<model id="Followers" limit="999" query="true" createrowifnonefound="false" sobject="User" orderby="Name">
<fields>
<field id="Name"/>
<field id="Id"/>
<field id="SmallPhotoUrl"/>
<field id="FirstName"/>
<field id="LastName"/>
<field id="Country"/>
<field id="State"/>
<field id="Title"/>
<field id="MobilePhone"/>
<field id="TimeZoneSidKey"/>
<field id="AboutMe"/>
<field id="City"/>
<field id="CompanyName"/>
<field id="Department"/>
<field id="Division"/>
<field id="Email"/>
<field id="Extension"/>
<field id="LanguageLocaleKey"/>
<field id="Phone"/>
<field id="Street"/>
<field id="FullPhotoUrl"/>
<field id="Username"/>
<field id="PostalCode"/>
</fields>
<conditions>
<condition type="modelmerge" value="" field="Id" operator="in" model="EntitySubscriptionFollowers" enclosevalueinquotes="true" mergefield="SubscriberId" state="filterableon" inactive="false" name="Followers"/>
<condition type="fieldvalue" value="true" enclosevalueinquotes="false" field="IsActive"/>
</conditions>
</model>
Photo of Stephen Chan

Stephen Chan

  • 956 Points 500 badge 2x thumb

Posted 5 years ago

  • 1
Photo of Stephen Chan

Stephen Chan

  • 956 Points 500 badge 2x thumb
In case it's not obvious, the Followers model gets the list of followers for a record, when the underlying EntitySubscription data changes, I can't just call updateData on the Followers and EntitySubscriptionFollowers models to re-query the dependent EntitySubscriptionFollowers model so that it refreshes the modelmerge condition and return the "latest" list for followers.
Photo of Zach McElrath

Zach McElrath, Employee

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

The dependent Model will only requery itself successfully if the Model it depends on is sent concurrently in the updateData call --- so you need to send both EntitySubscriptionFollowers and Followers into your updateData call, like this:



var EntitySubscriptionFollowers = skuid.model.getModel('EntitySubscriptionFollowers');
var Followers = skuid.model.getModel('Followers');

skuid.model.updateData([EntitySubscriptionFollowers,Followers]);



Any Conditions you have already applied on your EntitySubscriptionFollowers Model, i.e. via EntitySubscriptionFollowers.setCondition(conditionName,value), would be retained in this updateData call.

So for instance say that you make the ParentId field on your EntitySubscriptionFollowers a Filterable Condition, like this:



Then, say that you have your own Account picker, or something like that, and you want to go requery both your EntitySubscriptionFollowers and Followers Models based on the selected Account. Here's how you could do it:




var ESF = skuid.model.getModel('EntitySubscriptionFollowers');
var ESFParentId = ESF.getConditionByName('ParentId');
ESF.setCondition(ESFParentId,selectedAccountId);
var Followers = skuid.model.getModel('Followers');

skuid.model.updateData([ESF,Followers],function(){
console.log('update data complete!');
});

Photo of Stephen Chan

Stephen Chan

  • 956 Points 500 badge 2x thumb
Thanks again Zac for the fast turnaround, this looked promising but it didn't work for me :-(...I checked the requests behind the scenes and the individual queries are executing and returning the right (latest) records but the parent model soql statement doesn't seem to get updated with the new results from the dependent model? We are on 3.15, slightly old but is there something else I'm doing wrong?
Photo of Zach McElrath

Zach McElrath, Employee

  • 49,056 Points 20k badge 2x thumb
Hi Stephen --- could you post the exact JavaScript code you wrote, and perhaps post the resultant SOQL queries for both Models?

Are you saying that you updated both of your Models concurrently, using one updateData call, and that both Models returned the correct results you were expecting, but that the SOQL on your EntitySubscriptionFollowers model was not updated correctly?
Photo of Stephen Chan

Stephen Chan

  • 956 Points 500 badge 2x thumb
Hi Zac,

Sorry for the short reply earlier, I'm on leave so couldn't give more details. I know it's important to give you something to work off so I've quickly tried to isolate the issue a little more (the actual scenario is a visualforce/skuid hybrid so harder to give you something you can work with).

I've given you a simple page with the two models, entitysubscription and followers. The page is trying to show the list of followers for a record so you need to supply the id of a record in the url, e.g. https://skuid.cs6.visual.force.com/ap.... I picked a random account with no followers and followed it. Then I load this skuid page and inspect the underlying skuid models using the browser console:

1. Since the record has one follower the results are correct after page load:


followersModel.soql
"SELECT Id,PostalCode,Username,FullPhotoUrl,Street,Phone,LanguageLocaleKey,Extension,Email,Division,Department,CompanyName,City,AboutMe,TimeZoneSidKey,MobilePhone,Title,State,Country,LastName,FirstName,SmallPhotoUrl,Name FROM User WHERE ((Id in ('00590000001WKBKAA4'))AND(IsActive = true)) ORDER BY Name LIMIT 1000"

followersModel.data.length
1

entitySubscriptionFollowersModel.soql
"SELECT Id,Parent.Name,ParentId,Subscriber.Name,SubscriberId FROM EntitySubscription WHERE ((ParentId = '001N0000007BuF8')) LIMIT 1000"

entitySubscriptionFollowersModel.data.length
1


2. Then we open a new tab, go to the record page and stop following the record so that it no longer has any followers.

3. Then we go back to the skuid page and run the multiple update data call as discussed (to try and pick up the changes):


skuid.model.updateData([entitySubscriptionFollowersModel,followersModel],function(){console.log('complete')})
complete
<pre><code>

3. The followers model does not seem to refresh it's query and still returns one follower:

followersModel.soql
"SELECT Id,PostalCode,Username,FullPhotoUrl,Street,Phone,LanguageLocaleKey,Extension,Email,Division,Department,CompanyName,City,AboutMe,TimeZoneSidKey,MobilePhone,Title,State,Country,LastName,FirstName,SmallPhotoUrl,Name FROM User WHERE ((Id in ('00590000001WKBKAA4'))AND(IsActive = true)) ORDER BY Name LIMIT 1000"

followersModel.data.length
1

4. But the dependant entitysubscription model runs correctly and shows there are no followers so why does the follower model above not pick this up?


entitySubscriptionFollowersModel.soql
"SELECT Id,Parent.Name,ParentId,Subscriber.Name,SubscriberId FROM EntitySubscription WHERE ((ParentId = '001N0000007BuF8')) LIMIT 1000"

entitySubscriptionFollowersModel.data.length
0


Hope that makes things clearer and you can reproduce it or tell me what I'm doing wrong.

Thanks for looking at this.

Cheers,
Stephen



<skuidpage showsidebar="false" showheader="false">
<resources>
<labels/>
<javascript>
<jsitem location="inline" name="PageLoad">var cefiType = 'News';
var entitySubscriptionFollowersModel = null;
var followersModel = null;

jQuery(document).ready(function() {
entitySubscriptionFollowersModel = skuid.model.getModel('EntitySubscriptionFollowers');
followersModel = skuid.model.getModel('Followers');
});
</jsitem>
</javascript>
<css/>
</resources>
<models>
<model id="EntitySubscriptionFollowers" limit="999" query="true" createrowifnonefound="false" sobject="EntitySubscription">
<fields>
<field id="SubscriberId"/>
<field id="Subscriber.Name"/>
<field id="ParentId"/>
<field id="Parent.Name"/>
</fields>
<conditions>
<condition type="param" value="id" field="ParentId" operator="=" userinfotype="userid" enclosevalueinquotes="true"/>
</conditions>
</model>
<model id="Followers" limit="999" query="true" createrowifnonefound="false" sobject="User" orderby="Name">
<fields>
<field id="Name"/>
<field id="Id"/>
<field id="SmallPhotoUrl"/>
<field id="FirstName"/>
<field id="LastName"/>
<field id="Country"/>
<field id="State"/>
<field id="Title"/>
<field id="MobilePhone"/>
<field id="TimeZoneSidKey"/>
<field id="AboutMe"/>
<field id="City"/>
<field id="CompanyName"/>
<field id="Department"/>
<field id="Division"/>
<field id="Email"/>
<field id="Extension"/>
<field id="LanguageLocaleKey"/>
<field id="Phone"/>
<field id="Street"/>
<field id="FullPhotoUrl"/>
<field id="Username"/>
<field id="PostalCode"/>
</fields>
<conditions>
<condition type="modelmerge" value="" field="Id" operator="in" model="EntitySubscriptionFollowers" enclosevalueinquotes="true" mergefield="SubscriberId" state="filterableon" inactive="false" name="Followers"/>
<condition type="fieldvalue" value="true" enclosevalueinquotes="false" field="IsActive"/>
</conditions>
</model>
</models>
<components>
<skootable showconditions="true" showsavecancel="false" searchmethod="client" searchbox="true" showexportbuttons="false" pagesize="5" createrecords="false" model="Followers" mode="readonly" uniqueid="FollowersTable">
<fields>
<field id="SmallPhotoUrl" columnwidth="" type="CUSTOM" snippet="RenderChatterPhoto" readonly="true">
<label>Followers</label>
</field>
<field id="Name" type="" snippet="RenderChatterLike" columnwidth="90%" readonly="true">
<label>&amp;nbsp;</label>
</field>
</fields>
<rowactions>
<action type="popup" window="self" icon="ui-silk-folder-explore" label="Details">
<popup title="Details for {{Name}}" width="900">
<components>
<pagetitle model="Followers">
<actions>
<action type="custom" label="Close" icon="ui-silk-cross" snippet="ClosePopup"/>
</actions>
<conditions>
<condition type="contextrow" field="Id" autocreated="true"/>
</conditions>
</pagetitle>
<panelset type="standard">
<panels>
<panel width="300" type="left">
<components>
<basicfieldeditor showheader="true" showsavecancel="false" model="Followers" mode="readonly" layout="above">
<columns>
<column width="100%">
<sections>
<section title="Name">
<fields>
<field id="Name" type="CUSTOM" snippet="RenderText"/>
<field id="FullPhotoUrl" type="CUSTOM" snippet="RenderPhotoLarge" readonly="false">
<label/>
</field>
</fields>
</section>
</sections>
</column>
</columns>
<conditions>
<condition type="contextrow" field="Id" autocreated="true"/>
</conditions>
</basicfieldeditor>
</components>
</panel>
<panel>
<components>
<basicfieldeditor showheader="true" showsavecancel="false" model="Followers" mode="readonly">
<columns>
<column width="50%">
<sections>
<section title="Details">
<fields>
<field id="Title"/>
<field id="Department"/>
<field id="TimeZoneSidKey"/>
<field id="AboutMe"/>
</fields>
</section>
</sections>
</column>
<column width="50%">
<sections>
<section title="Contact">
<fields>
<field id="MobilePhone"/>
<field id="Phone"/>
<field id="Extension"/>
<field id="Email" type="CUSTOM" snippet="RenderText"/>
</fields>
</section>
<section title="Address">
<fields>
<field id="Street"/>
<field id="City"/>
<field id="PostalCode"/>
<field id="State"/>
<field id="Country"/>
</fields>
</section>
</sections>
</column>
</columns>
<conditions>
<condition type="contextrow" field="Id" autocreated="true"/>
</conditions>
</basicfieldeditor>
</components>
</panel>
</panels>
</panelset>
</components>
</popup>
</action>
</rowactions>
<views>
<view type="standard"/>
</views>
<filters/>
</skootable>
</components>
</skuidpage>
Photo of Zach McElrath

Zach McElrath, Employee

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

Thanks for the detailed description of the problem, this helped a lot. I think that you can resolve this by installing the latest version of Skuid, which includes a new property on Field from another Model Conditions called "No Value Behavior" that was designed to fix the problem you are experiencing.

Here is the install link for sandboxes:

https://test.salesforce.com/packaging/installPackage.apexp?p0=04tG00000008LML

Basically, go to the "Id in ... " Condition on your Followers Model, and click on the Value attribute, and there should be a new property called "No Value Behavior". Select "Abort Query" instead of deactivate Condition. Basically what this does is to tell Skuid that, if the source Model (EntitySubscriptionFollowers here) returns no records, then there's no point in running the Followers Model's SOQL query at all --- so it will return 0 rows as expected, rather than doing what it is currently doing now.

Photo of Stephen Chan

Stephen Chan

  • 956 Points 500 badge 2x thumb
Sorry for the delay Zac, was on leave and just got back.

We're almost there...I upgraded to 3.22 and re-ran the scenario and the bug fix works but only if the ESF query returns 0 rows (my bad for simplifying to a zero vs one record case). The more realistic scenario is if you have two or more followers (ESF query result not zero) and then add/remove a follower. In this case the Follower model does not perform the same "No Value Behaviour = Abort Query" logic and doesn't refresh it's condition from the ESF model query result and you get the same issue, does this make sense?

Is there some way to "force" the model to re-query AND rebuild the conditions like it does on page load or "abort query" scenario?
Photo of Zach McElrath

Zach McElrath, Employee

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

As long as you use skuid.model.updateData([EntitySubscriptionFollowersModel,FollowersModel]) to re-query BOTH Models at the same time, then it should work. I've tried this on my test page and it works fine moving from 0 to 1 followers, from 1 to 0 followers, from 1 to 2, from 2 to 1... each time the Models are updated appropriately.



var ESF = skuid.model.getModel('EntitySubscriptionFollowers');
var ESFParentId = ESF.getConditionByName('ParentId');
ESF.setCondition(ESFParentId,selectedAccountId);
var Followers = skuid.model.getModel('Followers');
skuid.model.updateData([ESF,Followers],function(){
console.log('update data complete!');
});






Photo of Stephen Chan

Stephen Chan

  • 956 Points 500 badge 2x thumb
Hi Zac,

Thanks for confirming it works for you, I began to think it was something I did wrong so I re-ran everything from scratch and I still get the same result...however after much persistence trying different approaches I think I have a workaround!

I re-tried something that didn't work before but seems to work perfectly now in conjunction with the skuid.model.updateData on both models (which I wasn't using before). For some reason if I call the skuid.model.resetCondition on the dependent modelmerge condition before the updateData, the Followers model picks up the change correctly! Maybe you can tell me what's special about resetCondition because even more interestingly I only need to call it once on the model on page load and never have to call it again AND it works in my older 3.15 version of Skuid so I don't need to upgrade to 3.22 (yet)? The 2 lines of code were just:


followersModelCondition = followersModel.getConditionByName('Followers');
followersModel.resetCondition(followersModelCondition);

Appreciate the help driving me to this workaround!

Cheers,
Stephen