Renderer: Open Drawer

  • 1
  • Question
  • Updated 4 years ago
  • Answered
Any way to render a row action button in a table only if the row's drawer is open?
Photo of Scott

Scott

  • 2,722 Points 2k badge 2x thumb

Posted 4 years ago

  • 1
Photo of Rob Hatch

Rob Hatch, Official Rep

  • 44,006 Points 20k badge 2x thumb
Put the button in the drawer.   (GRIN)

Otherwize no - there is not a way to only render a button when a drawer is open. 

We are rolling out a new feature for drawers in the next release that will allow you to define an "open icon".    This second icon will take the place of the Row Action icon used to open the drawer.  So you could have a down arrow for close state,  and it would change to an up arrow when the drawer is open.  

Niether of these two answers may be what you are looking for.  But they are what I've got today.. 
Photo of Scott

Scott

  • 2,722 Points 2k badge 2x thumb
thanks wise-guy (SCOWL)...
I can't put it in the drawer because it adds a new row to a model and it needs to capture data from the row in the parent model.  The only way to do this is put the row add button in the parent row (correct?).

My problem is that, for some reason, when I add a row to the child model from the parent model and the drawer is closed, the "required field" option is ineffective (i.e. I can't add a row without a required field).  This seems to only happen when the drawer is closed and has not yet been opened.  So I thought that it might help if the button to add only appeared when the drawer was open.  Can this be done any other way?  JS?  What about adding a button in a template field on the row?

I like the "Open Icon" idea... any update on closing one drawer when another is opened?

Thanks Rob!
Photo of mB Pat Vachon

mB Pat Vachon, Champion

  • 42,714 Points 20k badge 2x thumb
I just had this the other day. You can put global actions in the child table that creates a row with a default value to reference the parent using {{Id}}.
The table just needs to have context setup.
(Edited)
Photo of Scott

Scott

  • 2,722 Points 2k badge 2x thumb
thanks pat.
i actually went a different route here.
Photo of Barry Schnell

Barry Schnell, Champion

  • 18,086 Points 10k badge 2x thumb
Hey Scott -

This actually can be done.  Not sure which route you went but you have two options that I can think of here:

1) Add a new checkbox/boolean field to your object (and model) and use conditional rendering on the row action based on the value in that field.  Use "run multiple actions" and as a second action, call a snippet that inverses the value of this field.  I don't think you can use "update field on row" because the value would need to be static in the declarative interface.  Here, we want (NOT CurrentValue) to inverse it.  Since the row action is conditioned on the value in this field, it will auto hide/show.

2) To avoid adding a field just for this, below is another solution.  Using "run multiple actions", a snippet will get called each time the drawer is open/closed.  Within the snippet, we detect the drawer state and show/hide other icons accordingly.  As you'll see in the comments of the snippet code itself, while both of the methods for accomplishing this are likely to have long term sustainability, it is using some constructs of skuid that could change and therefore likely be an unsupported solution.  That said, I would think it's fairly unlikely to change :)

Here is a sample page with the snippet included:

<skuidpage unsavedchangeswarning="yes" showsidebar="true" showheader="true" tabtooverride="Account">   <models>
      <model id="Account" limit="100" query="true" createrowifnonefound="false" sobject="Account">
         <fields>
            <field id="Name"/>
            <field id="CreatedDate"/>
         </fields>
         <conditions/>
         <actions/>
      </model>
      <model id="Contact" limit="20" query="true" createrowifnonefound="false" sobject="Contact" doclone="" type="">
         <fields>
            <field id="Name"/>
            <field id="FirstName"/>
            <field id="LastName"/>
            <field id="AccountId"/>
            <field id="Account.Name"/>
         </fields>
         <conditions/>
         <actions/>
      </model>
   </models>
   <components>
      <skootable showconditions="true" showsavecancel="false" searchmethod="server" searchbox="false" showexportbuttons="false" pagesize="10" createrecords="false" model="Account" mode="read" buttonposition="">
         <fields>
            <field id="Name" allowordering="true" valuehalign="" type="" snippet="accountRenderer"/>
            <field id="CreatedDate" allowordering="true"/>
         </fields>
         <rowactions>
            <action type="edit"/>
            <action type="delete"/>
            <action type="multi" label="Show Contacts" icon="sk-icon-magic">
               <drawer title="Drawer Area" width="800" closehandle="true">
                  <components/>
               </drawer>
               <actions>
                  <action type="drawer">
                     <drawer title="Drawer Area" width="800" closehandle="true">
                        <components>
                           <skootable showconditions="true" showsavecancel="false" searchmethod="server" searchbox="true" showexportbuttons="false" pagesize="10" createrecords="true" model="Contact" buttonposition="" mode="read">
                              <fields>
                                 <field id="FirstName"/>
                                 <field id="LastName"/>
                                 <field id="Name"/>
                              </fields>
                              <rowactions/>
                              <massactions usefirstitemasdefault="true"/>
                              <views>
                                 <view type="standard"/>
                              </views>
                              <conditions>
                                 <condition type="contextrow" field="AccountId" mergefield="Id"/>
                              </conditions>
                              <actions defaultlabel="Global Actions" defaulticon="sk-icon-magic" usefirstitemasdefault="true">
                                 <action type="multi" label="Add New Multiple" icon="sk-icon-add">
                                    <drawer title="Drawer Area" width="800" closehandle="true">
                                       <components/>
                                    </drawer>
                                    <actions>
                                       <action type="createRow" model="Contact" appendorprepend="prepend" defaultmodefornewitems="edit"/>
                                    </actions>
                                 </action>
                                 <action type="createrow" appendorprepend="prepend" label="Add New Direct">
                                    <drawer title="Drawer Area" width="800" closehandle="true">
                                       <components/>
                                    </drawer>
                                 </action>
                              </actions>
                           </skootable>
                        </components>
                     </drawer>
                  </action>
                  <action type="custom" snippet="toggleRowActionVisibility"/>
               </actions>
               <renderconditions logictype="and"/>
            </action>
            <action type="multi" label="Hide This If Drawer Is Not Visible" icon="sk-icon-activities reqdraweropen">
               <drawer title="Drawer Area" width="800" closehandle="true">
                  <components/>
               </drawer>
               <actions>
                  <action type="blockUI" message="You can only click this if the drawer is open" timeout="3000"/>
               </actions>
               <renderconditions logictype="and"/>
            </action>
            <action type="multi" label="Go to Home Page" icon="sk-icon-convert reqdraweropen">
               <drawer title="Drawer Area" width="800" closehandle="true">
                  <components/>
               </drawer>
               <actions>
                  <action type="blockUI" message="Hide this one too" timeout="3000"/>
               </actions>
            </action>
         </rowactions>
         <massactions usefirstitemasdefault="true"/>
         <views>
            <view type="standard"/>
         </views>
         <searchfields/>
      </skootable>
   </components>
   <resources>
      <labels/>
      <css/>
      <javascript>
         <jsitem location="inline" name="rowActionVisibility" cachelocation="false" url="">(function(skuid) {
    // shorthand to jquery
var $ = skuid.$
   // the class used to identify row actions we want to hide when drawer is not open
   // this class should be included on any row action that is applicable
   , reqdrawerclass = '.reqdraweropen';
// register a document.ready function to hide all icons on initial display
$(function(){
        $(reqdrawerclass).hide();
    });
    // this uses a selector based on the known class that skuid applies
    // to rows that have drawers.  While possible, the class name
    // is unlikely to change so this is a rather safe long-term solution
    // However, because the animations on the drawer (slideup/slidedown) occurs
    // asynchronously and for the slidup one, the class itself is toggled within the animation
    // so if we check for the class immediately here it will always be here except on initial
    // display.  We need to wait for the animation to complete and then can check
    // if the row still has a drawer open.  THe below applies a 500ms delay
    // but this will need to vary based on a number of factors.  Technically
    // this produces the result we want, just not very elegant since we could end
    // up missing the hide/show or if we do catch it right, there is still a delay
    // on the UI when the icons appear/disappear.
    // See the medium risk solution for another option
    var lowRiskSolution = function(item) {
        var element = item &amp;&amp; item.element;
        // if we have an element
        if (element) {        
            
            // build in a delay
            setTimeout(function() {
                // check for the known skuid class that is applied to a row that contains a drawer
                // and show/hide our special class based on answer
                if ($(element).hasClass('nx-item-has-drawer')) {
                    $(element).find(reqdrawerclass).show();
                }
                else {
                    $(element).find(reqdrawerclass).hide();
                }
            }, 500); // this might need to be increased
        }            
    };
    // this uses internally unsupported non-documented items from skuid
    // while it should support future compatibility there are no guarantees.
    // the above solution provides a safer long term solution even though it itself
    // is unsupported.  This solution is more reliable and better UI/UX.
    var mediumRiskSolution = function(item) {
        var drawer = item.drawers &amp;&amp; item.drawers[0]
        , element = item &amp;&amp; item.element
        , $ = skuid.$;
        
        // if we have a drawer
        if (drawer) {
            // get anything we want to show/hide
            var icons = $(element).find(reqdrawerclass);
            
            // if we're open, show it, else hide it
            drawer.isOpen ? $(icons).show() : $(icons).hide();
        }
    };
    
// snippet to toggle visibility of the icons based on drawer open/close status
skuid.snippet.registerSnippet('toggleRowActionVisibility', function(args) {
        var eventArg = arguments[0]
        , item = eventArg.item
        , drawer = item.drawers &amp;&amp; item.drawers[0]
        , element = item &amp;&amp; item.element;
        // if we have an item
        if (item) {
            // this will call the low risk but not ideal solution
       //lowRiskSolution(item);
       
       // this will call the better technical solution but risk for future
       // compatibility is slightly higher
       mediumRiskSolution(item);
        }        
});
})(skuid);</jsitem>
      </javascript>
   </resources>
</skuidpage>