cross model linked conditions

  • 5
  • Idea
  • Updated 2 years ago
  • Implemented
Photo of mB Pat Vachon

mB Pat Vachon, Champion

  • 43,016 Points 20k badge 2x thumb

Posted 4 years ago

  • 5
Photo of mB Pat Vachon

mB Pat Vachon, Champion

  • 43,016 Points 20k badge 2x thumb
Official Response
The javascript snippet to enable this was relatively easy.

var $ = skuid.$,
    eliteAgentAccounts_Ag = skuid.$M('EliteAgentAccounts_Ag'),
    eliteAgentAccounts_Basic = skuid.$M('EliteAgentAccounts_Basic');
    
    $.each(eliteAgentAccounts_Ag.conditions, function(i,condition){
        
        var agConditionName = condition.name,
            basicCondition = eliteAgentAccounts_Basic.getConditionByName(agConditionName);

        if(condition.inactive) {
            eliteAgentAccounts_Basic.deactivateCondition(basicCondition);
        } else {
            eliteAgentAccounts_Basic.activateCondition(basicCondition);
            eliteAgentAccounts_Basic.setCondition(basicCondition,condition.value);
        }

    });
Photo of Oliver Sinfield

Oliver Sinfield

  • 922 Points 500 badge 2x thumb
Pat, you're a legend! I was only today, thinking about how to have one date picker that will filter a bunch of other models. Mucho useful for charting, as well as building dynamic report type pages.
Photo of Rob Hatch

Rob Hatch, Official Rep

  • 44,308 Points 20k badge 2x thumb
Pat is taking a page out of my book.  Asking a question and then answering it himself.  That's awesome.  But we do miss the hats. 
Photo of Irvin Waldman

Irvin Waldman, Champion

  • 9,016 Points 5k badge 2x thumb
Pat,

I had a rock star developer who worked for me when I ran a start up moons ago. He worked remotely and there were days that he went w/o seeing daylight. Your picture reminder me (fondly) of that developer. Rock on, dude.

Irvin
Photo of Joe Ort

Joe Ort

  • 2,266 Points 2k badge 2x thumb
Pardon the javascript newbie...

I have 2 aggregate models that are identical except the 2nd doesn't have any groupings (so I can have call-out numbers).  I basically did a find and replace with the code here (I replaced the basic model with my model without groups and the other with my aggregate that has the table filters). The display numbers aren't being filtered...

It's an in-line (snippet) as follows:

var $ = skuid.$,    oppyAggregate = skuid.$M('OppyAggregate'),
    oppyAggregatetoDisplay = skuid.$M('OppyAggregatetoDisplay');
    
    $.each(oppyAggregate.conditions, function(i,condition){
        
        var agConditionName = condition.name,
            basicCondition = oppyAggregatetoDisplay.getConditionByName(agConditionName);
        if(condition.inactive) {
            oppyAggregatetoDisplay.deactivateCondition(basicCondition);
        } else {
            oppyAggregatetoDisplay.activateCondition(basicCondition);
            oppyAggregatetoDisplay.setCondition(basicCondition,condition.value);
        }
    });
Photo of Joe Ort

Joe Ort

  • 2,266 Points 2k badge 2x thumb
Bump
Photo of Jonathan Gillespie

Jonathan Gillespie

  • 870 Points 500 badge 2x thumb
Joe, I'm not sure if this is the same issue that you're having, but I found that Pat's original snippet doesn't handle unnamed conditions that are always active - I had to slightly tweak it to get it to work for my models.

I added one extra if statement to my snippet

if(!agConditionName) {
return true;
}

Here's a modified version of your snippet that incorporates it.

var $ = skuid.$, oppyAggregate = skuid.$M('OppyAggregate'),
oppyAggregatetoDisplay = skuid.$M('OppyAggregatetoDisplay');

$.each(oppyAggregate.conditions, function(i,condition){

var agConditionName = condition.name,
basicCondition = oppyAggregatetoDisplay.getConditionByName(agConditionName);
if(!agConditionName) {
return true;
} else if(condition.inactive) {
oppyAggregatetoDisplay.deactivateCondition(basicCondition);
} else {
oppyAggregatetoDisplay.activateCondition(basicCondition);
oppyAggregatetoDisplay.setCondition(basicCondition,condition.value);
}
(Edited)
Photo of Rob Hatch

Rob Hatch, Official Rep

  • 44,568 Points 20k badge 2x thumb
Joe,  I don't immediately see anything wrong with your code.   Would you mind giving us login rights to your org so we can take a look at what is going on?   Here is how:
1. Use this tutorial to give us login rights: http://help.skuidify.com/m/getting-started/l/182412-getting-help-how-to-grant-skuid-login-rights-to-....
2. Then send an email to support@skuidify.com  with the name of the page. 
We'll see what's going on...
Photo of Rob Hatch

Rob Hatch, Official Rep

  • 44,308 Points 20k badge 2x thumb
Here are  a few clarifications we found about Pat's snippet. 

1. Implementation: 
- This snippet should be of type "Inline Snippet"
- You need to create a model action on the first model (the one that has filters on it) that is triggered when you requery the model. 
- The actions need to be "Run Snippet" and "Query Model" - choosing the second model. 

2. Limitations: 
- This code will not work for multipicklist conditions.  There is a diffent API method for passing values into multi-picklist conditions. 
Photo of Anna Wiersema

Anna Wiersema

  • 10,910 Points 10k badge 2x thumb
You guys are geniuses, and by geniuses, I mean the kind of people whose code the rest of us cannibalize so we can live another day without learning Javascript.

Here's the XML for a page that demonstrates this in action, for my fellow copy-pasters. It has 3 models queried with one filter, that I created for this topic. Yay!
Photo of Anna Wiersema

Anna Wiersema

  • 10,910 Points 10k badge 2x thumb
<skuidpage unsavedchangeswarning="yes" showsidebar="true" showheader="true">
   <models>
<model id="Leads" limit="10" query="true" createrowifnonefound="false" sobject="Lead" doclone="" type="">
<fields>
<field id="Name"/>
<field id="CreatedDate"/>
</fields>
<conditions>
<condition type="fieldvalue" value="" enclosevalueinquotes="false" field="CreatedDate" state="filterableoff" inactive="true" name="CreatedDate"/>
</conditions>
<actions>
<action>
<actions>
<action type="custom" snippet="newSnippet"/>
<action type="requeryModels" model="Leads" behavior="standard">
<models>
<model>Contacts</model>
<model>Tasks</model>
</models>
</action>
</actions>
<events>
<event>models.loaded</event>
</events>
</action>
</actions>
</model>
<model id="Contacts" limit="10" query="true" createrowifnonefound="false" sobject="Contact" doclone="" type="">
<fields>
<field id="Name"/>
<field id="CreatedDate"/>
</fields>
<conditions>
<condition type="fieldvalue" value="THIS_WEEK" enclosevalueinquotes="false" field="CreatedDate" state="filterableoff" inactive="true" name="CreatedDate"/>
</conditions>
<actions/>
</model>
<model id="Tasks" limit="10" query="true" createrowifnonefound="false" sobject="Task" doclone="" type="">
<fields>
<field id="Subject"/>
<field id="CreatedDate"/>
</fields>
<conditions>
<condition type="fieldvalue" value="THIS_WEEK" enclosevalueinquotes="false" field="CreatedDate" state="filterableoff" inactive="true" name="CreatedDate"/>
</conditions>
<actions/>
</model>
</models>
<components>
<pagetitle model="Contacts">
<maintitle>This filter, though.</maintitle>
<actions>
<action type="multi" label="Created This Week" icon="fa-filter">
<actions>
<action type="activateCondition" model="Leads" condition="CreatedDate"/>
<action type="activateCondition" model="Contacts" condition="CreatedDate"/>
<action type="activateCondition" model="Tasks" condition="CreatedDate"/>
<action type="requeryModels" behavior="standard">
<models>
<model>Leads</model>
<model>Contacts</model>
<model>Tasks</model>
</models>
</action>
</actions>
</action>
<action type="multi" label="Remove Filter" icon="sk-icon-cancel">
<actions>
<action type="deactivateCondition" model="Leads" condition="CreatedDate"/>
<action type="deactivateCondition" model="Leads" condition="CreatedDate"/>
<action type="deactivateCondition" model="Leads" condition="CreatedDate"/>
<action type="requeryModels" model="Leads" behavior="standard">
<models>
<model>Leads</model>
<model>Contacts</model>
<model>Tasks</model>
</models>
</action>
</actions>
</action>
<action type="savecancel">
<models>
<model>Leads</model>
<model>Tasks</model>
</models>
</action>
</actions>
</pagetitle>
<skootable showconditions="true" showsavecancel="false" searchmethod="server" searchbox="false" showexportbuttons="false" pagesize="all" createrecords="false" model="Leads" buttonposition="" mode="readonly" cssclass="hidetablefooter" emptysearchbehavior="query">
<fields/>
<rowactions/>
<massactions usefirstitemasdefault="true"/>
<views/>
<searchfields/>
<filters>
<filter type="select" filteroffoptionlabel="Created Any Time" createfilteroffoption="true" affectcookies="true" autocompthreshold="25" conditionsource="manual" labelmode="manual" label="Created Date" condition="CreatedDate">
<sources>
<source type="manual" effectsbehavior="justdefault">
<options>
<option label="Last Month" type="simple" value="LAST_MONTH"/>
<option label="This Month" type="simple" value="THIS_MONTH"/>
</options>
</source>
</sources>
</filter>
</filters>
</skootable>
<panelset type="custom" scroll="">
<panels>
<panel width="33.3%">
<components>
<skootable showconditions="true" showsavecancel="false" searchmethod="server" searchbox="false" showexportbuttons="false" pagesize="10" createrecords="true" model="Contacts" buttonposition="" mode="read" emptysearchbehavior="query">
<fields>
<field id="Name"/>
<field id="CreatedDate"/>
</fields>
<rowactions>
<action type="edit"/>
<action type="delete"/>
</rowactions>
<massactions usefirstitemasdefault="true">
<action type="massupdate"/>
<action type="massdelete"/>
</massactions>
<views>
<view type="standard"/>
</views>
<searchfields/>
</skootable>
</components>
</panel>
<panel width="33.3%">
<components>
<skootable showconditions="true" showsavecancel="false" searchmethod="server" searchbox="false" showexportbuttons="false" pagesize="10" createrecords="true" model="Leads" buttonposition="" mode="read" emptysearchbehavior="query">
<fields>
<field id="Name"/>
<field id="CreatedDate"/>
</fields>
<rowactions>
<action type="edit"/>
<action type="delete"/>
</rowactions>
<massactions usefirstitemasdefault="true">
<action type="massupdate"/>
<action type="massdelete"/>
</massactions>
<views>
<view type="standard"/>
</views>
<searchfields/>
</skootable>
</components>
</panel>
<panel width="33.3%">
<components>
<skootable showconditions="true" showsavecancel="false" searchmethod="server" searchbox="false" showexportbuttons="false" pagesize="10" createrecords="true" model="Tasks" buttonposition="" mode="read" instantfilters="false" emptysearchbehavior="query">
<fields>
<field id="Subject"/>
<field id="CreatedDate"/>
</fields>
<rowactions>
<action type="edit"/>
<action type="delete"/>
</rowactions>
<massactions usefirstitemasdefault="true">
<action type="massupdate"/>
<action type="massdelete"/>
</massactions>
<views>
<view type="standard"/>
</views>
<searchfields/>
</skootable>
</components>
</panel>
</panels>
</panelset>
</components>
<resources>
<labels/>
<javascript>
<jsitem location="inlinesnippet" name="newSnippet" cachelocation="false">var $ = skuid.$,
Leads = skuid.$M('Leads'),
Contacts = skuid.$M('Contacts'),
Tasks = skuid.$M('Tasks');

$.each(Leads.conditions, function(i,condition){

var LeadConditionName = condition.name,
ContactsCondition = Contacts.getConditionByName(LeadConditionName)
TasksCondition = Tasks.getConditionByName(LeadConditionName);

if(condition.inactive) {
Contacts.deactivateCondition(ContactsCondition),
Tasks.deactivateCondition(TasksCondition);
} else {
Contacts.activateCondition(ContactsCondition);
Contacts.setCondition(ContactsCondition,condition.value);
Tasks.activateCondition(TasksCondition);
Tasks.setCondition(TasksCondition,condition.value);
}

});</jsitem>
</javascript>
<css>
<cssitem location="inline" name="hidetablefooter" cachelocation="false">.hidetablefooter .nx-list-footer {
display:none;
}
</cssitem>
</css>
</resources>
</skuidpage>
(Edited)
Photo of Tami Lust

Tami Lust

  • 5,376 Points 5k badge 2x thumb
Hi Ana,

Should this work with using a Date Range filter. 

Thanks,

Tami
Photo of Rob Hatch

Rob Hatch, Official Rep

  • 44,308 Points 20k badge 2x thumb
I would not be suprised if this DOES NOT work with Date Range filters. 
Photo of Tami Lust

Tami Lust

  • 5,376 Points 5k badge 2x thumb
So far I have not been able to get this to work with a Date Range. Do you know of another way that a date range can work on a table and its drawer?
Photo of mB Pat Vachon

mB Pat Vachon, Champion

  • 43,016 Points 20k badge 2x thumb
interesting. Table model and drawer model. Should still work. You may have to modify snippet slightly.

Not sure about updating already opened drawer though.
Photo of Matt Sones

Matt Sones, Champion

  • 31,904 Points 20k badge 2x thumb
Tami / Rob - 

If you use a date range with manual conditions it should work (I have it working on several pages). You may not be able to do it with the the automatically generated date range conditions.
Photo of Tami Lust

Tami Lust

  • 5,376 Points 5k badge 2x thumb
Matt,

Can you explain more about the manual conditions? I have a date range with manual condition set on the parent table. How would I go about having it also change the drawer data?
Photo of Tami Lust

Tami Lust

  • 5,376 Points 5k badge 2x thumb
Pat,

I tried your snippet with a date range and I couldn't get it to work. Further inspection of how the date range shows in the console and the "value" section doesn't get filled in. There are two conditions that need to be changed a Start and End date. Perhaps your snippet could work with some changes but I am not versed enough at this point to know what those changes should be.
Photo of Matt Sones

Matt Sones, Champion

  • 31,904 Points 20k badge 2x thumb
Tami,

Here are two snippets, modified from Pat's. The first I use to initialize the date range on the primary model on pageload. The second I use to link the conditions each time the primary model is queried. You need a conditions called "StartDate" and "EndDate" on each model that you want to link.

<jsitem location="inline" name="initializeDateConditions" cachelocation="false" url="">(function(skuid){
var $ = skuid.$;
$(document.body).one('pageload',function(){
var dateRangeModel = skuid.$M('Cases'),
    startDateCondition = dateRangeModel.getConditionByName('StartDate'),
    endDateCondition =  dateRangeModel.getConditionByName('EndDate'),
    startDate = new Date(),
    endDate = new Date(),
    startDateOffset = -15,
    endDateOffset = -1;
   
    startDate.setDate(startDate.getDate() + startDateOffset);
        endDate.setDate(endDate.getDate() + endDateOffset);
    
        var startConditionValue = skuid.time.getSFDateTime(startDate),
            endConditionValue = skuid.time.getSFDateTime(endDate);
        
        dateRangeModel.setCondition(startDateCondition, startConditionValue);
        dateRangeModel.setCondition(endDateCondition, endConditionValue);
    
        dateRangeModel.updateData();
    
});
})(skuid);</jsitem>
      <jsitem location="inlinesnippet" name="linkConditions" cachelocation="false">var $ = skuid.$;
var startValue = skuid.$M('Cases').getConditionByName('StartDate').value,
    endValue = skuid.$M('Cases').getConditionByName('EndDate').value;
var targetModels = [];
targetModels.push(skuid.$M('numberOfSchedulingLeads'));
$.each(targetModels, function(){
   this.setCondition(this.getConditionByName('StartDate'), startValue);
   this.setCondition(this.getConditionByName('EndDate'), endValue);
});
</jsitem>

After you run the linking script, you'll need to query the linked (drawer) model.
(Edited)
Photo of Dave

Dave

  • 5,670 Points 5k badge 2x thumb
Hi Matt,

I'm trying to use same principle to get this idea working, and wondering if you think it could work.

I have some sort of "Dashboard" built on Skuid, which contains 15+ models

And i want to Be able to input 1 Date Range manually (prob 2 ui only date fields , 1 for startdate , 1 for enddate- as cannot use automatically generated filters)

and once date range is inputted for it to affect all 15 models with same condition name

Any ideas?
Photo of mB Pat Vachon

mB Pat Vachon, Champion

  • 43,016 Points 20k badge 2x thumb
This would certainly work. As Matt has done, you could name all the filters in each model with the same names so that you could create a snippet to loop through the models in order to update each of their conditions and then query them after which.

If you want to update every model in your page with your ui only fields, then you could loop through them using skuid.model.list(). If not, create an array of the model id's to loop through in this way.

var models = ['model1','model2',....],
      model;


$.each(models, function(m,modelid)({
   model = skuid.$M('modelid')
   // update model conditions
   ....
});
Photo of Matt Sones

Matt Sones, Champion

  • 31,904 Points 20k badge 2x thumb
I'd just put a pagetitle with an 'apply' button next to your date range fields, and have the button run a snippet that goes something like this:

var $ = skuid.$;
$.blockUI();
var row = skuid.$M('MyUiOnlyModel').getFirstRow(),
    startValue = row.StartDate
    endValue = row.EndDate;
var targetModels = skuid.model.list(); 
// If you don't want to apply the condition to all of your models, // you can list them manually in the targetModels array like so: // var targetModels = [skuid.$M('Model1'),skuid.$M('Model2')];
$.each(targetModels, function(){
   this.setCondition(this.getConditionByName('StartDate'), startValue);
   this.setCondition(this.getConditionByName('EndDate'), endValue);
}); $.when(skuid.model.updateData(targetModels)).then(function(){ $.unblockUI(); });
(Edited)
Photo of Dave

Dave

  • 5,670 Points 5k badge 2x thumb
HI Matt & Pat,

Thank you and  Sorry was a bit busy and was only able to test this today.

I created a model named MyUiOnlyModel , and 2 Ui-only fields in it, named StartDate and EndDate
+ create 2 condition (filterable off) in 1 other model to test , condition are named StartDate and EndDate

Apply button has 1 Action: Run the Snippet above

When i try it, i get this error in console :  Uncaught Model 'MyUiOnlyModel' has unsaved changes. To update this model's data, you must first save or cancel the changes.

On the model named 'MyUiOnlyModel', I unchecked the option to Prevent users from leaving page if this Model has unsaved change, but Still having same error

The UI is stuck and cannot test properly because of it.

Any Ideas?

Thank you
Photo of mB Pat Vachon

mB Pat Vachon, Champion

  • 43,016 Points 20k badge 2x thumb
The "MyUiOnlyModel" must be set to query as well. You'll have to cancel the changes prior to query but after setting conditions.
Photo of Dave

Dave

  • 5,670 Points 5k badge 2x thumb
Thank you , been trying, but nothing works. i guess not knowledgeable enough in JS to modify Matt's Script on my own :(

In case any of you have a similar script you are already using please share, so i can try to understand it.


var $ = skuid.$;
$.blockUI();
var row = skuid.$M('MyUiOnlyModel').getFirstRow(),
    startValue = row.StartDate
    endValue = row.EndDate;
var targetModels = skuid.model.list(); 
// If you don't want to apply the condition to all of your models, // you can list them manually in the targetModels array like so: // var targetModels = [skuid.$M('Model1'),skuid.$M('Model2')];
$.each(targetModels, function(){
   this.setCondition(this.getConditionByName('StartDate'), startValue);
   this.setCondition(this.getConditionByName('EndDate'), endValue);
}); $.when(skuid.model.updateData(targetModels)).then(function(){ $.unblockUI(); });
Photo of Laura Burnett

Laura Burnett

  • 588 Points 500 badge 2x thumb
Hi All,

I've also been trying to edit this snippet, to no avail. My use case:

  • Two different objects, both with a multipicklist that uses a global picklist
  • If I filter object A, I want object B to also filter

My code is below, where the two models in Skuid are named 'Projects' and 'Focus_Area_Grouping'. The model is named "Focus_Area_Grouping' in both objects.

var $ = skuid.$,    Projects = skuid.$M('Projects'),
    Focus_Area_Grouping = skuid.$M('Focus_Area_Grouping');
    
    $.each(Projects.conditions, function(i,condition){
        
        var agConditionName = condition.name,
            Focus_Area_Groupings__c = Focus_Area_Grouping.getConditionByName(Focus_Area_Groupings__c);

        if(condition.inactive) {
            Focus_Area_Grouping.deactivateCondition(Focus_Area_Groupings__c);
        } else {
            Focus_Area_Grouping.activateCondition(Focus_Area_Groupings__c);
            Focus_Area_Grouping.setCondition(Focus_Area_Groupings__c,condition.value);
        }

    });


Additionally, I also tried this:
var $ = skuid.$, Projects = skuid.$M('Projects'),Focus_Area_Grouping = skuid.$M('Focus_Area_Grouping');

$.each(Projects.conditions, function(i,condition){

var agConditionName = condition.name,
basicCondition = Focus_Area_Grouping.getConditionByName(agConditionName);
if(!agConditionName) {
return true;
} else if(condition.inactive) {
Focus_Area_Grouping.deactivateCondition(basicCondition);
} else {
Focus_Area_Grouping.activateCondition(basicCondition);
Focus_Area_Grouping.setCondition(basicCondition,condition.value);
}


Any help welcome!
Photo of Matt Sones

Matt Sones, Champion

  • 31,954 Points 20k badge 2x thumb
If you're only dealing with one condition, you don't need the `$.each`.

Try something like this...

var $ = skuid.$,
    Projects = skuid.$M('Projects'),
    Focus_Area_Grouping = skuid.$M('Focus_Area_Grouping');
    
var projectsCondition = Projects.getConditionByName('Focus_Area_Grouping'),
    focusAreaGroupingCondition = Focus_Area_Grouping.getConditionByName('Focus_Area_Grouping');
    if(projectsCondition.inactive) {
   Focus_Area_Grouping.deactivateCondition(focusAreaGroupingCondition);
} else {
   Focus_Area_Grouping.setCondition(focusAreaGroupingCondition, projectsCondition.value);
}