WIzard & depending model issues.

  • 1
  • Problem
  • Updated 4 years ago
  • Solved
Hi,

I am building a wizard that does an employee appraisal. The first step is to capture who the appriasal is on, and some other high level data about the appraisal. Once I have that, in step1, I want to load a set of appraisal questions based on the employee record identified in the first step.

I have tried all kinds of things, including late loading models through javascript, conditions that are turned on and off via a save of the initial condition, and whatever I try simply does not work.... Any suggestions on how to do this?

Here is the XML for what I've done so far... 

<skuidpage unsavedchangeswarning="yes" showsidebar="false" showheader="true">
   <models>
      <model id="AppraisalInputData" limit="1" query="false" createrowifnonefound="true" sobject="Appraisal__c" doclone="" type="" forview="true">
         <fields>
            <field id="Name"/>
            <field id="Appraisee__c"/>
            <field id="Appraisee__r.Name"/>
            <field id="Owner.Name"/>
            <field id="Period__c"/>
            <field id="Type__c"/>
            <field id="Year__c"/>
            <field id="Id"/>
            <field id="Appraisee__r.Id"/>
         </fields>
         <conditions/>
         <actions>
            <action>
               <actions>
                  <action type="activateCondition" model="AppraisalQueriedData" condition="whereclause"/>
                  <action type="requeryModels" behavior="standard">
                     <models>
                        <model>AppraisalQueriedData</model>
                        <model>Employee</model>
                        <model>Competencies</model>
                     </models>
                  </action>
               </actions>
               <events>
                  <event>models.saved</event>
               </events>
            </action>
         </actions>
      </model>
      <model id="AppraisalQueriedData" limit="1" query="false" createrowifnonefound="false" sobject="Appraisal__c" doclone="" type="" forview="true">
         <fields>
            <field id="Name"/>
            <field id="Appraisee__c"/>
            <field id="Appraisee__r.Name"/>
            <field id="General_Assessment__c"/>
            <field id="OwnerId"/>
            <field id="Owner.Name"/>
            <field id="Period__c"/>
            <field id="Score__c"/>
            <field id="Status__c"/>
            <field id="Type__c"/>
            <field id="Year__c"/>
            <field id="Id"/>
            <field id="Appraisee__r.Id"/>
         </fields>
         <conditions>
            <condition type="modelmerge" value="" field="Name" operator="=" model="AppraisalInputData" enclosevalueinquotes="true" mergefield="Name" novaluebehavior="noquery" state="filterableoff" inactive="true" name="whereclause"/>
         </conditions>
         <actions/>
      </model>
      <model id="Employee" limit="1" query="false" createrowifnonefound="false" sobject="Employee__c" doclone="no" type="">
         <fields>
            <field id="CoE__c"/>
            <field id="CoE__r.Name"/>
            <field id="Name"/>
            <field id="Location__c"/>
            <field id="Location__r.Name"/>
            <field id="Id"/>
            <field id="RoleLevel__c"/>
            <field id="RoleLevel__r.Name"/>
            <field id="System_User__c"/>
            <field id="System_User__r.Name"/>
         </fields>
         <conditions>
            <condition type="modelmerge" value="" field="System_User__c" operator="=" model="AppraisalQueriedData" enclosevalueinquotes="true" mergefield="Appraisee__c" novaluebehavior="deactivate" state=""/>
         </conditions>
         <actions/>
      </model>
      <model id="Competencies" limit="30" query="false" createrowifnonefound="false" sobject="Competency__c" doclone="no" type="" orderby="SortOrder__c">
         <fields>
            <field id="Assessment_question__c"/>
            <field id="Category__c"/>
            <field id="CoE__c"/>
            <field id="CoE__r.Name"/>
            <field id="Name"/>
            <field id="Description__c"/>
            <field id="RoleLevel__c"/>
            <field id="RoleLevel__r.Name"/>
            <field id="Self_Assessment_Question__c"/>
            <field id="Sub_category__c"/>
            <field id="Id"/>
            <field id="SortOrder__c"/>
         </fields>
         <conditions logic="((1 AND 2) OR (1 AND 4) OR (2 AND 3) OR (3 AND 4))">
            <condition type="fieldvalue" value="*" enclosevalueinquotes="true" field="CoE__r.Name" operator="=" state=""/>
            <condition type="fieldvalue" value="*" enclosevalueinquotes="true" field="RoleLevel__r.Name"/>
            <condition type="modelmerge" value="" field="CoE__c" operator="=" model="Employee" enclosevalueinquotes="true" mergefield="CoE__c" novaluebehavior="noquery"/>
            <condition type="modelmerge" value="" field="RoleLevel__c" operator="=" model="Employee" enclosevalueinquotes="true" mergefield="RoleLevel__c" novaluebehavior="noquery"/>
         </conditions>
         <actions/>
      </model>
   </models>
   <components>
      <pagetitle model="AppraisalInputData">
         <maintitle>
            <template>{{Name}}</template>
         </maintitle>
         <subtitle>
            <template>{{Model.label}}</template>
         </subtitle>
         <actions/>
      </pagetitle>
      <wizard deferstepcontentsrendering="true" uniqueid="MyWizard">
         <steps>
            <step stepid="Appraisee" steplabel="Appraisee Data" loadlazypanels="true">
               <components>
                  <pagetitle model="AppraisalInputData">
                     <subtitle>Please capture the specific details regarding the individual being appraised. This will be used to load in their competencies, corporate goals and individual goal assessment screens. </subtitle>
                     <actions/>
                  </pagetitle>
                  <basicfieldeditor showheader="true" showsavecancel="false" model="AppraisalInputData" buttonposition="" mode="edit" layout="">
                     <columns>
                        <column width="100%">
                           <sections>
                              <section title="Section B" collapsible="no" showheader="false">
                                 <fields>
                                    <field id="Appraisee__c" showhelp="true" valuehalign="" type="" required="true"/>
                                    <field id="Type__c" valuehalign="" type="" required="true"/>
                                    <field id="Period__c" valuehalign="" type="" required="true"/>
                                    <field id="Year__c" valuehalign="" type="" required="true"/>
                                 </fields>
                              </section>
                           </sections>
                        </column>
                     </columns>
                  </basicfieldeditor>
               </components>
               <actions>
                  <action type="save" stepid="Competency Assessment" label="Next" icon="sk-icon-arrow-right" window="self" rollbackonanyerror="true">
                     <actions>
                        <action type="save" rollbackonanyerror="false">
                           <models>
                              <model>AppraisalNew</model>
                           </models>
                        </action>
                        <action type="navigateToStep" stepid="Competency Assessment"/>
                     </actions>
                     <models>
                        <model>AppraisalInputData</model>
                     </models>
                     <hotkeys/>
                     <renderconditions logictype="and"/>
                  </action>
               </actions>
            </step>
            <step stepid="Competency Assessment" steplabel="Competency Assessment" loadlazypanels="true">
               <components>
                  <pagetitle model="Competencies">
                     <actions/>
                     <subtitle>Please provide your assessment against &lt;strong&gt;all&lt;/strong&gt; competencies listed on the left. Click &lt;strong&gt;Next&lt;/strong&gt; once you have completed all competency assessments.</subtitle>
                  </pagetitle>
                  <skootable showconditions="true" showsavecancel="false" searchmethod="server" searchbox="true" showexportbuttons="false" pagesize="10" createrecords="false" model="AppraisalQueriedData" buttonposition="" mode="read">
                     <fields>
                        <field id="Name" valuehalign="" type=""/>
                        <field id="Appraisee__c"/>
                        <field id="Period__c"/>
                        <field id="Year__c"/>
                        <field id="Type__c"/>
                     </fields>
                     <rowactions>
                        <action type="edit"/>
                        <action type="delete"/>
                     </rowactions>
                     <massactions usefirstitemasdefault="true">
                        <action type="massupdate"/>
                        <action type="massdelete"/>
                     </massactions>
                     <views>
                        <view type="standard"/>
                     </views>
                  </skootable>
                  <skootable showconditions="true" showsavecancel="false" searchmethod="server" searchbox="true" showexportbuttons="false" pagesize="10" createrecords="false" model="Employee" buttonposition="" mode="readonly">
                     <fields>
                        <field id="CoE__c"/>
                        <field id="Name"/>
                        <field id="Location__c"/>
                        <field id="RoleLevel__c"/>
                        <field id="System_User__c"/>
                     </fields>
                     <rowactions/>
                     <massactions usefirstitemasdefault="true"/>
                     <views>
                        <view type="standard"/>
                     </views>
                  </skootable>
                  <skootable showconditions="true" showsavecancel="true" searchmethod="server" searchbox="true" showexportbuttons="false" pagesize="10" createrecords="true" model="Competencies" buttonposition="" mode="read">
                     <fields>
                        <field id="CoE__c"/>
                        <field id="Category__c"/>
                        <field id="SortOrder__c"/>
                        <field id="Self_Assessment_Question__c"/>
                        <field id="RoleLevel__c"/>
                        <field id="Description__c"/>
                        <field id="Sub_category__c"/>
                        <field id="Assessment_question__c"/>
                     </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>
               <actions>
                  <action type="navigate" label="Previous" stepid="Appraisee" window="self" icon="fa-arrow-left"/>
                  <action type="navigate" label="Next" stepid="Corporate Goals Assessment" window="self" icon="fa-arrow-right"/>
               </actions>
            </step>
            <step stepid="Corporate Goals Assessment" steplabel="Corporate Goals Assessment" loadlazypanels="true">
               <components/>
               <actions>
                  <action type="navigate" label="Previous" stepid="Competency Assessment" window="self" icon="fa-arrow-left"/>
                  <action type="navigate" label="Next" stepid="Individual Goals Assessment" window="self" icon="fa-arrow-right"/>
               </actions>
            </step>
            <step stepid="Individual Goals Assessment" steplabel="Individual Goals Assessment" loadlazypanels="true">
               <components/>
               <actions>
                  <action type="navigate" label="Previous" stepid="Corporate Goals Assessment" window="self" icon="fa-arrow-left"/>
                  <action type="navigate" label="Next" stepid="General Assessment" window="self" icon="fa-arrow-right"/>
               </actions>
            </step>
            <step stepid="General Assessment" steplabel="General Assessment" loadlazypanels="true">
               <components/>
               <actions>
                  <action type="navigate" label="Previous" stepid="Individual Goals Assessment" window="self" icon="fa-arrow-left"/>
                  <action type="save" label="Save" stepid="General Assessment" window="self" icon="sk-icon-save" rollbackonanyerror="true">
                     <models>
                        <model>Appraisal</model>
                     </models>
                  </action>
               </actions>
            </step>
         </steps>
         <renderconditions logictype="and"/>
      </wizard>
   </components>
   <resources>
      <labels/>
      <javascript>
         <jsitem location="inline" name="LazyLoadModelData" cachelocation="false" url="">//WIZARD STEP MODEL INITIALISER
// working okay - Monday 9/3/2015
// Loads the relevant models when a step in the wizard is activated
// (to avoid the models needing to 
//run on the initial page load).)

(function(skuid){
    var $ = skuid.$;
  
    var modelsToLoadByStep = {
    // note, need the Input data here, as otherwise the whereconditions are not applied server-side -- but doesn't seem to work! :(
    //'Competency Assessment': ['AppraisalInputData','AppraisalQueriedData']
    //'Competency Assessment': ['AppraisalInputData','AppraisalQueriedData','Employee', 'Competencies']
    'Competency Assessment': []

    };
    
    var loadingMessage = 'Loading Appraisal Data...';
// If true, then we'll only try to load our models
// if there's no data in them,
// which presumably won't be true 
// if we've already queried for data in them
    var onlyLoadIfEmpty = false;
//$(function() {
    $(document.body).one('pageload',function(){
        $('#MyWizard').on('stepchange',function(e,data){
            var stepPanel = data.currentStep,
                modelsToLoad = [];
    
            if (stepPanel.id in modelsToLoadByStep) {
                $.each(modelsToLoadByStep[stepPanel.id],function(i,modelId){
                    var model = skuid.$M(modelId);
                    if (!onlyLoadIfEmpty || !model.data.length) {
                        modelsToLoad.push(model); 
                    }
                });
                if (modelsToLoad.length){
                    
                    //skuid.model.updateData(modelsToLoad);
                    
                    
                    stepPanel.element.block({
                        message: loadingMessage,
                        css:{
                            top:'50px'
                        }
                    }); 
                    
                    $.when(skuid.model.updateData(modelsToLoad))
                    .then(function(){
                       stepPanel.element.unblock();
                    });
                    
                }
            }
        });
    });
})(skuid);</jsitem>
      </javascript>
      <css/>
   </resources>
</skuidpage>
 
Photo of Bradley Wood

Bradley Wood

  • 424 Points 250 badge 2x thumb
  • frustrated

Posted 4 years ago

  • 1
Photo of Matt Sones

Matt Sones, Champion

  • 31,478 Points 20k badge 2x thumb
brad,

I haven't looked at your XML in detail, but in general I would try creating a different wizard step for each type of employee record. Create a different nav button on your first page for each type. Then apply conditional rendering to the buttons so that only the correct button appears.

If you have a huge number of different types, that might be too cumbersome.
Photo of Bradley Wood

Bradley Wood

  • 424 Points 250 badge 2x thumb
I should have said that the specific issue I'm having is not with navigation back and forward, nor branching (as there is no branching needed). The issue is with models... I have the following models.

  • Appraisal Record (input) model - this creates a new appraisal record on page 1 of the wizard. I save this on clicking through to the next page of the wizard.
  • Employee Model (which I load depending on the above Employee field in the Appraisal model. 
  • Depending on the employee record, I need to load a load of questions in the second page (Competencies model). 
When I save the Appraisal model on page one, I want to enforce a condition on the Competency and Employee model which are read-only and should look up a specific employee record and set of competencies I want to appraise.

The conditions on these latter 2 models do not work --- this is the issue.
Photo of Matt Sones

Matt Sones, Champion

  • 31,478 Points 20k badge 2x thumb
brad,

Your action sequence for the navigation to the second page should include:
  1. Save the Appraisal Record model
  2. Activate and set the conditions on your other models
  3. Query the other models.
I don't see a reason why that shouldn't work?
Photo of Bradley Wood

Bradley Wood

  • 424 Points 250 badge 2x thumb
Thanks Matt, but no joy :(...  Here is the relevant dependent model with the filterable condition off:

<model id="Employee" limit="1" query="false" createrowifnonefound="false" sobject="Employee__c" doclone="no" type="">
         <fields>
            <field id="CoE__c"/>
            <field id="CoE__r.Name"/>
            <field id="Name"/>
            <field id="Location__c"/>
            <field id="Location__r.Name"/>
            <field id="Id"/>
            <field id="RoleLevel__c"/>
            <field id="RoleLevel__r.Name"/>
            <field id="System_User__c"/>
            <field id="System_User__r.Name"/>
         </fields>
         <conditions>
            <condition type="fieldvalue" value="" state="filterableoff" inactive="true" operator="=" field="Id" mergefield="Id" novaluebehavior="deactivate" name="employeewhereclause" enclosevalueinquotes="true"/>
         </conditions>
         <actions/>
      </model>

And here is the button with the actions on it to save and then update the model condition. I don't load the model on this button as I have some lazy loading javascript that will do that later.

<action type="multi" stepid="Competency Assessment" label="Next" icon="sk-icon-arrow-right" window="self" rollbackonanyerror="true">
                     <actions>
                        <action type="save">
                           <models>
                              <model>Appraisal</model>
                           </models>
                        </action>
                        <action type="setCondition" model="Employee" condition="employeewhereclause" value="{{$Model.Appraisal.data.0.Id}}"/>
                        <action type="navigateToStep" stepid="Competency Assessment"/>
                     </actions>
                     <models>
                        <model>Appraisal</model>
                     </models>
                     <hotkeys/>
                     <renderconditions logictype="and"/>
                  </action>

do I need to do the button stuff as a JS snippet do you think?
Photo of Matt Sones

Matt Sones, Champion

  • 31,478 Points 20k badge 2x thumb
Brad, I think you just need to query the employee model after you activate the filter.
Photo of Rob Hatch

Rob Hatch, Official Rep

  • 44,006 Points 20k badge 2x thumb
Yup, I too think the Model Query is the missing piece.   Thanks for your help Matt. 
Photo of Bradley Wood

Bradley Wood

  • 424 Points 250 badge 2x thumb
Thanks guys... Here is what I now have -- the annoying thing now, is that my "Next Button" on the wizard doesn't want to load the second step of the wizard.... I've disabled all the javascript for now, and am just trying to do this all via the gui.

Models:

<model id="Appraisal" limit="1" query="false" createrowifnonefound="true" sobject="Appraisal__c" doclone="" type="" forview="true">
         <fields>
            <field id="Name"/>
            <field id="Appraisee__c"/>
            <field id="Appraisee__r.Name"/>
            <field id="Owner.Name"/>
            <field id="Period__c"/>
            <field id="Type__c"/>
            <field id="Year__c"/>
            <field id="Id"/>
            <field id="Appraisee__r.Id"/>
         </fields>
         <conditions/>
         <actions>
            <action>
               <actions>
                  <action type="save">
                     <models>
                        <model>Appraisal</model>
                     </models>
                  </action>
                  <action type="requeryModel" model="Appraisal" behavior="standard"/>
                  <action type="activateCondition" model="Employee" condition="employeewhereclause"/>
                  <action type="requeryModel" model="Employee" behavior="standard"/>
               </actions>
               <events>
                  <event>models.saved</event>
               </events>
            </action>
         </actions>
      </model>
      




<model id="Employee" limit="1" query="false" createrowifnonefound="false" sobject="Employee__c" doclone="no" type="">
         <fields>
            <field id="CoE__c"/>
            <field id="CoE__r.Name"/>
            <field id="Name"/>
            <field id="Location__c"/>
            <field id="Location__r.Name"/>
            <field id="Id"/>
            <field id="RoleLevel__c"/>
            <field id="RoleLevel__r.Name"/>
            <field id="System_User__c"/>
            <field id="System_User__r.Name"/>
         </fields>
         <conditions>
            <condition type="modelmerge" value="" field="System_User__c" operator="=" model="Appraisal" enclosevalueinquotes="true" mergefield="Appraisee__c" novaluebehavior="deactivate" state="filterableoff" inactive="true" name="employeewhereclause"/>
         </conditions>
         <actions/>
      </model>


The button to move to the next step in the wizard is here:

<actions>
                  <action type="save" stepid="Competency Assessment" label="Next" icon="sk-icon-arrow-right" window="self" rollbackonanyerror="true">
                     <actions>
                        <action type="save" rollbackonanyerror="true">
                           <models>
                              <model>Appraisal</model>
                           </models>
                        </action>
                        <action type="custom" snippet="UpdateConditionsFromAppraisalInput"/>
                        <action type="navigateToStep" stepid="Competency Assessment"/>
                     </actions>
                     <models>
                        <model>Appraisal</model>
                     </models>
                     <hotkeys/>
                     <renderconditions logictype="and"/>
                  </action>
               </actions>


Any idea why this is not moving forward when clicked?

Many thanks

Brad
Photo of Bradley Wood

Bradley Wood

  • 424 Points 250 badge 2x thumb
I've checked and check this and it should work -- the next button is saving (and I can see that via the SF gui), so the on-save stuff should trigger... It seems to take a long enough time when I click the "Next" button to suggest that something substantial is going on... But for some reason it refuses to navigate to the next step, even though the "Save" button type on the wizard supports that. 

Photo of Matt Sones

Matt Sones, Champion

  • 31,478 Points 20k badge 2x thumb
Brad,

Your first on-save action is Save. Sounds like an infinite loop.
Photo of Bradley Wood

Bradley Wood

  • 424 Points 250 badge 2x thumb
Exactly right Matt!! I just found a stack overflow in the JavaScript console, so I removed that... Now an even weirder thing seems to happen...

The Next button saves and moves me to the next step. I briefly see the ID of my newly created Appraisal record which is new (autonumber is incrementing) but then it appears to be replaced by an old one a half-second later.... Is this some kind of weird race condition?

I will change all the stepids to be without spaces now and try moving the triggers to the button rather than as a model action... thanks again for your help with this!!

I'm sure we'll get there in the end!

Brad
Photo of Matt Sones

Matt Sones, Champion

  • 31,478 Points 20k badge 2x thumb
Brad,

I think that stepid cannot have spaces.

On another note, it seems preferable to run your action sequence on button click, not with model actions.

If there's some compelling reason to leave your sequence on the model, having a Save Model action run in a sequence initiated by a Save event is probably not a good idea...
Photo of Rob Hatch

Rob Hatch, Official Rep

  • 44,006 Points 20k badge 2x thumb
Step ID can have spaces, but make sure you are not confusing your StepID and your Step Label Name.   The button action needs to call the ID. 



Another issue may be your snippet.   "UpdateConditionsFromAppraisalInput "  If it is failling, you won't know it and you wont go to the next action (which moves the step forward).   You can add an "On Failure" action to the snippet action that gives you some feedback if that is the issue. 



Good luck. 
Photo of Bradley Wood

Bradley Wood

  • 424 Points 250 badge 2x thumb
Thanks Rob.. I took out all JavaScript since the original post above, including that snippet for exactly the reason you suggest... The reason for the button not clicking through to the next tab was as Matt suggested -- infinite save loop with an on-save action telling it to save (doh!!)... So that is resoved now.. Cheers... Its just the filterable conditions which don't seem to apply now as described below.

Cheers

B
Photo of Bradley Wood

Bradley Wood

  • 424 Points 250 badge 2x thumb
Still no joy...  :(  It saves the Appraisal model, but it doesn't appear to by applying the filterable condition on Employee model on the next tab...

The condition on the Employee model is this:

1: System_user__c = (Appraisal)(Appraisee__c)(filterable as employeewhereclause)(inactive)

These fields (System_user__c and Appaisee__c) both reference the standard SF User object.
Models look like this now


<model id="Appraisal" limit="1" query="false" createrowifnonefound="true" sobject="Appraisal__c" doclone="" type="" forview="true">
         <fields>
            <field id="Name"/>
            <field id="Appraisee__c"/>
            <field id="Appraisee__r.Name"/>
            <field id="Owner.Name"/>
            <field id="Period__c"/>
            <field id="Type__c"/>
            <field id="Year__c"/>
            <field id="Id"/>
            <field id="Appraisee__r.Id"/>
         </fields>
         <conditions/>
         <actions/>
      </model>
      <model id="Employee" limit="1" query="false" createrowifnonefound="false" sobject="Employee__c" doclone="no" type="">
         <fields>
            <field id="CoE__c"/>
            <field id="CoE__r.Name"/>
            <field id="Name"/>
            <field id="Location__c"/>
            <field id="Location__r.Name"/>
            <field id="Id"/>
            <field id="RoleLevel__c"/>
            <field id="RoleLevel__r.Name"/>
            <field id="System_User__c"/>
            <field id="System_User__r.Name"/>
         </fields>
         <conditions>
            <condition type="modelmerge" value="" field="System_User__c" operator="=" model="Appraisal" enclosevalueinquotes="true" mergefield="Appraisee__c" novaluebehavior="deactivate" state="filterableoff" inactive="true" name="employeewhereclause"/>
         </conditions>
         <actions/>
      </model>

And the button

<actions>
                  <action type="multi" stepid="CompetencyAssessment" label="Next" icon="sk-icon-arrow-right" window="self" rollbackonanyerror="true">
                     <actions>
                        <action type="save" rollbackonanyerror="true">
                           <models>
                              <model>Appraisal</model>
                           </models>
                        </action>
                        <action type="activateCondition" model="Employee" condition="employeewhereclause"/>
                        <action type="requeryModel" model="Employee" behavior="standard"/>
                        <action type="navigateToStep" stepid="CompetencyAssessment"/>
                     </actions>
                     <models>
                        <model>Appraisal</model>
                     </models>
                     <hotkeys/>
                     <renderconditions logictype="and"/>
                  </action>
               </actions>
Photo of Bradley Wood

Bradley Wood

  • 424 Points 250 badge 2x thumb
So I've messed about with the filterable condition a bit now too.

I tried matching it on the Id field of the 2 objects, rather than the object itself. No luck.

Then I tried the Id again, but setting it to a specific value.

On the inactive model condition I set the value to "" and then, on the button click I set it to {{$Model.Appraisal.data.0.Appraisee__r.Id}}

AND THIS WORKED!  

Thanks for both of your help. 
(Edited)
Photo of Matt Sones

Matt Sones, Champion

  • 31,478 Points 20k badge 2x thumb
Glad you got it working, Brad.