Abort model's query only if all conditions have no rows in source model

  • 2
  • Problem
  • Updated 1 year ago
  • In Progress
Objective: I'd like to use a single table within a single page include that, 
  1. Returns the opportunities for a given account when passed an account Id
  2. Returns the opportunities for a given contact when passed a contact Id (via OpportunityContactRole)
Approach: I included the XML below, but here’s a summary of the models and conditions:

1) Account model
  • Condition: Id = AccountId URL param (novaluebehavior=“noquery")
2) OpportunityContactRole model
  • Condition: Id = ContactId URL param (novaluebehavior=“noquery")
3) Opportunity model
  • Condition logic: 1 OR 2
    1. Condition 1: AccountId = Id from the Account model (novaluebehavior=“deactivate")
    2. Condition 2: Id is in the set of OpportunityId values from the OpportunityContactRoles model (novaluebehavior=“deactivate")
Problem: This works perfectly except for when both the Account model and the OpportunityContactRole model don’t have rows. In this scenario, both conditions on the Opportunity model are deactivated but the query is still executed, so we end up with a table of random opportunities. 

Changing the "novaluebehavior” of the conditions on the Opportunity model from “deactivate” to “noquery” doesn’t work either because the query gets aborted if one of the first two models doesn’t have rows, which will always be the case.

XML:

<skuidpage unsavedchangeswarning="yes" personalizationmode="server" showsidebar="true" useviewportmeta="true" showheader="true">
    <models>
        <model id="Account" limit="1" query="true" createrowifnonefound="false" datasource="salesforce" type="" sobject="Account">
            <fields>
                <field id="Id"/>
                <field id="Name"/>
            </fields>
            <conditions>
                <condition type="param" value="AccountId" field="Id" operator="=" enclosevalueinquotes="true" novaluebehavior="noquery"/>
            </conditions>
            <actions/>
        </model>
        <model id="OpportunityContactRoles" limit="20" query="true" createrowifnonefound="false" datasource="salesforce" type="" sobject="OpportunityContactRole">
            <fields>
                <field id="ContactId"/>
                <field id="Contact.Name"/>
                <field id="OpportunityId"/>
                <field id="Opportunity.Name"/>
            </fields>
            <conditions>
                <condition type="param" value="ContactId" field="ContactId" fieldtargetobjects="Contact" operator="=" mergefield="Id" novaluebehavior="noquery" enclosevalueinquotes="true"/>
            </conditions>
            <actions/>
        </model>
        <model id="Opportunities" limit="20" query="true" createrowifnonefound="false" datasource="salesforce" type="" sobject="Opportunity">
            <fields>
                <field id="AccountId"/>
                <field id="Account.Name"/>
                <field id="Id"/>
                <field id="Name"/>
            </fields>
            <conditions logic="1 OR 2">
                <condition type="modelmerge" value="" field="AccountId" fieldtargetobjects="Account" operator="=" novaluebehavior="deactivate" model="Account" enclosevalueinquotes="true" mergefield="Id" state=""/>
                <condition type="modelmerge" value="" field="Id" operator="in" model="OpportunityContactRoles" enclosevalueinquotes="true" mergefield="OpportunityId" novaluebehavior="deactivate" state="" fieldtargetobjects="Opportunity"/>
            </conditions>
            <actions/>
        </model>
    </models>
    <components>
        <skootable showconditions="true" showsavecancel="false" showerrorsinline="true" searchmethod="server" searchbox="true" showexportbuttons="false" pagesize="10" alwaysresetpagination="false" createrecords="false" model="Account" buttonposition="" mode="readonly" allowcolumnreordering="true" responsive="true" uniqueid="sk-1JToFP-649">
            <fields>
                <field id="Id" hideable="true" uniqueid="fi-1JTyCd-752"/>
                <field id="Name" hideable="true" uniqueid="fi-1JTyCd-753"/>
            </fields>
            <rowactions/>
            <massactions usefirstitemasdefault="true"/>
            <views>
                <view type="standard"/>
            </views>
        </skootable>
        <skootable showconditions="true" showsavecancel="false" showerrorsinline="true" searchmethod="server" searchbox="true" showexportbuttons="false" pagesize="10" alwaysresetpagination="false" createrecords="false" model="OpportunityContactRoles" buttonposition="" mode="readonly" allowcolumnreordering="true" responsive="true" uniqueid="sk-1JTpys-663">
            <fields>
                <field id="ContactId" hideable="true" uniqueid="fi-1JTztw-762"/>
                <field id="OpportunityId" hideable="true" uniqueid="fi-1JTztw-763"/>
            </fields>
            <rowactions/>
            <massactions usefirstitemasdefault="true"/>
            <views>
                <view type="standard"/>
            </views>
        </skootable>
        <skootable showconditions="true" showsavecancel="false" showerrorsinline="true" searchmethod="server" searchbox="true" showexportbuttons="false" pagesize="10" alwaysresetpagination="false" createrecords="false" model="Opportunities" buttonposition="" mode="readonly" allowcolumnreordering="true" responsive="true" uniqueid="sk-1JTr2b-677">
            <fields>
                <field id="Id" hideable="true" uniqueid="fi-1JU0Bn-774" valuehalign="" type=""/>
                <field id="AccountId" hideable="true" uniqueid="fi-1JU0Bm-772"/>
                <field id="Name" hideable="true" uniqueid="fi-1JU0Bn-773"/>
            </fields>
            <rowactions/>
            <massactions usefirstitemasdefault="true"/>
            <views>
                <view type="standard"/>
            </views>
        </skootable>
    </components>
    <resources>
        <labels/>
        <javascript/>
        <css/>
    </resources>
    <styles>
        <styleitem type="background" bgtype="none"/>
    </styles>
</skuidpage>
Photo of Will Soupcoff

Will Soupcoff

  • 734 Points 500 badge 2x thumb

Posted 1 year ago

  • 2
Photo of Skuidward Tentacles (Raymond)

Skuidward Tentacles (Raymond), Champion

  • 17,224 Points 10k badge 2x thumb
Can you set your source page to only send AccountId parameter if there is an Account Id to send? The conditions have options as to what to do if a URL parameter is not found. One is deactivate condition. So, you could change your condition logic to 1 AND 2, then have the condition for AccountId deactivate if that parameter is not in the URL and the same for the ContactId.
Photo of Skuidward Tentacles (Raymond)

Skuidward Tentacles (Raymond), Champion

  • 17,224 Points 10k badge 2x thumb
You are correct. I whiffed on that one. Try three models:
1) an account model with a condition of receive your accountid parameter
2) a contact model to receive your contactid parameter
3) your primary model that has two conditions set to "in rows of another model". Set the condition logic to 1 OR 2.
Photo of Will Soupcoff

Will Soupcoff

  • 734 Points 500 badge 2x thumb
That's essentially what I have already except that I'm sending the ContactId to the OpportunityContactRole model, which I'm then using the conditions of my primary model.
Photo of Bill McCullough

Bill McCullough, Champion

  • 12,426 Points 10k badge 2x thumb
Will,

I think you are going to need to add an 'Inline' snippet to determine when to load the Opportunity model.  I don't think there is a declarative solution for this.

Thanks,

Bill
Photo of Will Soupcoff

Will Soupcoff

  • 734 Points 500 badge 2x thumb
Do you (or anyone else) have an example of what that might look like? I'm not opposed to a snippet, as long as it's relatively straightforward.
Photo of Bill McCullough

Bill McCullough, Champion

  • 12,426 Points 10k badge 2x thumb
Will,

This will get you started.  It needs to be 'Inline' JavaScript so that it runs on page load.

(function(skuid){
var $ = skuid.$;
$(document.body).one('pageload',function(){
//when the page loads into the browser
//check to see if the id parameter has a value.  if so load the account model
if(window.location.href.indexOf('id=') != -1) {
   //sets the id condition of the account model
   skuid.model.map().Account.cancel();
   var accountModel = skuid.model.getModel('Account');
   var accountCondition = accountModel.getConditionByName('Id');
   accountModel.setCondition(accountCondition,  window.location.href.split('id=')[1])
   accountModel.updateData();
}
});
})(skuid);

Thanks,

Bill
Photo of Amy Dewaal

Amy Dewaal, Official Rep

  • 8,200 Points 5k badge 2x thumb
Will, 
What do you want to happen? Do you want the table to show as blank? Do you want anything else to show instead? You could add rendering conditions on the table to hide it if both the oppcontact model and the account model don't have data rows. That may not be ideal depending on your use case, but at least your users wouldn't see a table of random opportunities. Another option would be to have two opportunity models on the page and two tables, one for each condition. You could render the proper one based on which model has data rows
Photo of Will Soupcoff

Will Soupcoff

  • 734 Points 500 badge 2x thumb
I would like the query to be aborted when all models referenced in the conditions have no rows, which would result in a table with no rows vs what's happening now, which is a table filled with random records.

My assumption is that even if I did hide the table when the other models don't have rows, the query for the table is still executed, which would impact performance.

Having multiple models and tables for the different scenarios is an option I've considered, but I'm attempting to reduce redundancies wherever I can so that my pages load faster and they're easier to maintain.