Disabling hyperlink to salesforce on reference field does not work On 'Edit and Cancel'

  • 1
  • Problem
  • Updated 4 years ago
  • Solved
  • (Edited)
Hi, 

I have a requirement of getting a Reference field  as a Picklist on 'edit' mode  and Completely removing/disabling  the hyperlink (to native salesforce UI)  on 'read' and 'readonly' mode using javascript snippet. 

I wrote following snippet to address the issue:


 field = arguments[0],
value = arguments[1],
$ = skuid.$;

    skuid.ui.fieldRenderers[field.metadata.displaytype][field.mode](field, value);
    
//If we are in edit mode render the reference field as pick list    
    if(field.mode === 'edit') {
        field.options.type = 'REFPICK';
        skuid.ui.fieldRenderers[field.metadata.displaytype][field.mode](field, value);

    }
// If we're  in read or readonly mode, then remove hyperlink 
if (field.mode !== 'edit') {
        var linkTag = $('a', field.element);
        if(linkTag.length){
            var output = $('<div>');
            output.append(linkTag.html());
        }   
linkTag.replaceWith(output);
}


This code works fine in all scenarios except 'edit and cancel'  scenario. When I edit a record (inline edit ) and cancel  without saving it the hyperlink reappears !

Is there any way around it? 

Thanks!
 -Jnanendra
Photo of Gyan

Gyan

  • 1,400 Points 1k badge 2x thumb

Posted 4 years ago

  • 1
Photo of Barry Schnell

Barry Schnell, Champion

  • 18,076 Points 10k badge 2x thumb
Hello Jnanendra -

Here is a snippet of what I've used to remove the hyperlink on reference fields.  You can add this as a static resource and set your field to use a "Custom (run snippet)" to render specifying removeHyperlinkRendererSnippet or just create an in-line snippet resource (removing the registerSnippet below), give it a name and then set the field to use that as the custom snippet.

Hope this helps!

skuid.snippet.registerSnippet('removeHyperlinkRendererSnippet', function(args) {	// let's make life a bit easier and and get some locally scoped variables
var field = arguments[0],
value = arguments[1],
renderer = skuid.ui.fieldRenderers[field.metadata.displaytype],
mode = field.mode,
$ = skuid.$;
// if we are not in edit mode
if (mode != 'edit') {
// there is a issue in skuid that does not properly clear out the relationship (__r) field
// when the relationship ID (__c) field gets set to null/empty.  For this reason, since in non-edit
// mode below we retrieve a value to display from the relationship field, we will end up with a value in there
// that is incorrect because the relationship id field (__c) is empty.  To workaround this, we
// check to see if we have a value in the relationship id field (represented by argument[1]) and if so, force
// an empty string to be displayed.  
// TODO: The "__r" not being cleared when "__c" is cleared is expected to be addressed by 
// skuid in a future release at which point this code can be simplified.
// we pass true as the third argument so we get the non-encoded version of the text value
var refFieldValue = value ? field.model.getFieldValue(field.row, skuid.utils.getFieldReference(field.id, field.metadata), true) : '';
// one last check to make sure we have something and don't display 'null' on the screen
var refFieldValue = refFieldValue || '';
// build the element using a DIV and adding skuid class to it
field.element.append(skuid.$('<div>').addClass('nx-fieldtext').text(refFieldValue));

// if we are in edit mode
else {
// Run standard renderer for the current mode
// (applies to read/edit mode)
renderer[mode](field,value);
}
});
Photo of Gyan

Gyan

  • 1,400 Points 1k badge 2x thumb
Hi Barry, 

Thank your for your reply.  Your code  (as well as mine) works great to remove the hyperlink from a reference field on 'read'  or 'readonly' mode. However, I want the reference field to be rendered as picklist on 'edit' mode.  To do that I added a line 

field.options.type = 'REFPICK';

just before last line (just after 'else' ) of your code. 




var field = arguments[0],
value = arguments[1],
renderer = skuid.ui.fieldRenderers[field.metadata.displaytype],
mode = field.mode,
$ = skuid.$;
// if we are not in edit mode
if (mode != 'edit') {
// there is a issue in skuid that does not properly clear out the relationship (__r) field
// when the relationship ID (__c) field gets set to null/empty.  For this reason, since in non-edit
// mode below we retrieve a value to display from the relationship field, we will end up with a value in there
// that is incorrect because the relationship id field (__c) is empty.  To workaround this, we
// check to see if we have a value in the relationship id field (represented by argument[1]) and if so, force
// an empty string to be displayed.  
// TODO: The "__r" not being cleared when "__c" is cleared is expected to be addressed by 
// skuid in a future release at which point this code can be simplified.
// we pass true as the third argument so we get the non-encoded version of the text value
var refFieldValue = value ? field.model.getFieldValue(field.row, skuid.utils.getFieldReference(field.id, field.metadata), true) : '';
// one last check to make sure we have something and don't display 'null' on the screen
var refFieldValue = refFieldValue || '';
// build the element using a DIV and adding skuid class to it
field.element.append(skuid.$('<div>').addClass('nx-fieldtext').text(refFieldValue));

// if we are in edit mode
else {
// Run standard renderer for the current mode
// (applies to read/edit mode)

field.options.type = 'REFPICK';

renderer[mode](field,value);
}




Now I can get the Picklist option on edit mode. However, I am still getting the same problem as before i.e. on  'edit and cancel'  scenario the hyperlink reappears after cancel. 

-Jnanendra
(Edited)
Photo of Barry Schnell

Barry Schnell, Champion

  • 18,076 Points 10k badge 2x thumb
Hello Jnanendra -

My apologies, I should have tested your specific scenario.  I too am getting the same behavior you are seeing when setting REFPICK before rendering in edit model.

In troubleshooting a bit further, it appears that after going in to "edit" mode the first time, the custom snippet never gets called to render the field again.  Since the renderer isn't getting called, I can't think of a way to workaround this other than to setup a listener to listen for cancel and then force a render of that field - although I'm not sure that will work based on what I describe below.  Additionally, even when you go out of edit mode without hitting cancel (by just clicking somewhere else on the screen for example), you end up with the hyperlink.

Steps to repro:
1) Create page using XML below
2)  open browser, display dev tools console and open the page specifying an account
3) Go in to edit mode, pick a different owner and click-off field
4) click cancel

Actual Result - Console Log indicates:
Renderer for OwnerId in mode read
Renderer for OwnerId in mode edit

Expected Result - Console Log indicates
Renderer for OwnerId in mode read (initial page load)
Renderer for OwnerId in mode edit (go to edit mode)
Renderer for OwnerId in mode read (change value and click off field to go back to read)
Renderer for OwnerId in mode read (cancel button)

<skuidpage showsidebar="true" showheader="true" tabtooverride="Account">   <models>
      <model id="Account" limit="1" query="true" createrowifnonefound="false" sobject="Account">
         <fields>
            <field id="Name"/>
            <field id="CreatedDate"/>
            <field id="OwnerId"/>
            <field id="Owner.Name"/>
         </fields>
         <conditions>
            <condition type="param" enclosevalueinquotes="true" operator="=" field="Id" value="id"/>
         </conditions>
      </model>
   </models>
   <components>
      <pagetitle model="Account">
         <maintitle>
            <template>{{Name}}</template>
         </maintitle>
         <subtitle>
            <template>{{Model.label}}</template>
         </subtitle>
         <actions>
            <action type="savecancel" window="self">
               <models>
                  <model>Account</model>
               </models>
            </action>
         </actions>
      </pagetitle>
      <basicfieldeditor showsavecancel="false" showheader="true" model="Account" mode="read">
         <columns>
            <column width="100%">
               <sections>
                  <section title="Basics">
                     <fields>
                        <field id="Name"/>
                        <field id="OwnerId" type="CUSTOM" snippet="ownerIdRenderer"/>
                     </fields>
                  </section>
               </sections>
            </column>
         </columns>
      </basicfieldeditor>
   </components>
   <resources>
      <labels/>
      <css/>
      <javascript>
         <jsitem location="inlinesnippet" name="ownerIdRenderer" cachelocation="false">var field = arguments[0],
    value = arguments[1],
    renderer = skuid.ui.fieldRenderers[field.metadata.displaytype],
    mode = field.mode,
    $ = skuid.$;
    
    console.log('Renderer for ' + field.id + ' in mode ' + mode);
    
    // if we are not in edit mode
    if (mode != 'edit') {
        // there is a issue in skuid that does not properly clear out the relationship (__r) field
        // when the relationship ID (__c) field gets set to null/empty.  For this reason, since in non-edit
        // mode below we retrieve a value to display from the relationship field, we will end up with a value in there
        // that is incorrect because the relationship id field (__c) is empty.  To workaround this, we
        // check to see if we have a value in the relationship id field (represented by argument[1]) and if so, force
        // an empty string to be displayed.  
        // TODO: The "__r" not being cleared when "__c" is cleared is expected to be addressed by 
        // skuid in a future release at which point this code can be simplified.
        // we pass true as the third argument so we get the non-encoded version of the text value
        var refFieldValue = value ? field.model.getFieldValue(field.row, skuid.utils.getFieldReference(field.id, field.metadata), true) : '';
        // one last check to make sure we have something and don't display 'null' on the screen
        var refFieldValue = refFieldValue || '';
        // build the element using a DIV and adding skuid class to it
        field.element.append(skuid.$('&lt;div&gt;').addClass('nx-fieldtext').text(refFieldValue));
    } 
    // if we are in edit mode
    else {
        // Run standard renderer for the current mode
        // (applies to read/edit mode)
        field.options.type = 'REFPICK';
        renderer[mode](field,value);
    }</jsitem>
      </javascript>
   </resources>
</skuidpage>
Photo of Barry Schnell

Barry Schnell, Champion

  • 18,076 Points 10k badge 2x thumb
Hello Jnanendra - 

I thought this through some more and it occurred to me what is likely happening.

When setting field.options.type to 'REFPICK', under the covers skuid is likely converting this to a "PICKLIST" field from a "CUSTOM".  Going along the lines of my theory, I tried the following and it worked!!

This is kind of hack'ish but hopefully will get you going.  Possibly someone more familiar with the inner workings can shed some light on why this is occuring or if there is a better solution than the below.

In the meantime, change the else for edit mode to:

       // temporarily set to REFPICK so we get the stock reference picklist functionality
       field.options.type = 'REFPICK';       
       // render away 
       renderer[mode](field,value);
       // set it back to custom
       field.options.type = 'CUSTOM';
(Edited)
Photo of Gyan

Gyan

  • 1,400 Points 1k badge 2x thumb
Thanks a lot Barry!
That was it!! Works like  a dream!!!

-Jnanendra