• Vance Kessler 23
  • NEWBIE
  • 10 Points
  • Member since 2015

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 12
    Questions
  • 13
    Replies
We had an AURA callback that passed -1 (integer) as a parameter which was accepted as a string parameter prior to Spring 19. After the release, it no longer even calls my APEX method. We fixed that by adding .toString() to the parameter.

My question is, WHAT CHANGED? I want to know if there are other places that Salesforce broke with this change.
WInter 19 had the following change:
The label attribute now supports text only. Previously the label supported a component type, and you could include, for example, an icon in the tab’s label. If you use a component in a lighting:tab label now, only the text portion of the label value displays. Any CSS classes that are applied are ignored.

The result is that I can no longer add classes to the tab. The following code no longer adds completed to the class attribute:
<lightning:tab id="Calendar" label="Calendar" class="{!v.CalendarHasSaved ? 'completed' : ''}">
Even if I have class="completed" it strips it out.

Why did they need to do this? I had styling that indicated whether a tab was 'complete' which no longer works.
In a Lightning controller, I need to determine if a user is in one of the Trusted IP address ranges. I could not find a way to retrieve the ranges, so I created a metadata setting to hold those values.

The problem now is that I cannot figure out what the user's ip address is to compare against that list of ranges.

How do I retrieve the current User's Ip Address in a Lightning component controller? Better yet, is there a setting/field/tea leaves I could check through Apex to tell if me the user is a trusted user?

I found the code below, but it appears to be for VisualForce pages because ApexPages.CurrentPage is always null in a component.
public static String GetUserIPAddress() {
	string returnValue = null;
	if (null != ApexPages.currentPage() ) {
		Map<String, String> headers = ApexPages.currentPage().getHeaders();
		returnValue = headers.get('True-Client-IP');

		if (returnValue == null) {
			returnValue = ApexPages.currentPage().getHeaders().get('X-Salesforce-SIP');
		} // get IP address when no caching (sandbox, dev, secure urls)
	}
	system.debug('USER IP ADDRESS: ' + returnValue);
	return returnValue;
}

 
I noticed that components respond to the force:refreshView event long after they have been removed from view. I wrote some test components that I placed on the Contact, Account, and Opportunity related list pages. If I navigate to a record of each type, they all continue to respond to the refreshView event. In fact, if I navigate to different accounts or contacts, each one continues to repsond to the refreshView event. I have found that it keeps a maximum of 4 components active in the background before actually destroying (unrendering) them.

In some components, we reload data on the refreshView event. Is there a way to know that reload of data is a waste of time?

Here is my test contact component:
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes">
    <aura:handler event="force:refreshView" action="{!c.refreshData}" />
    <ui:button label="Fire" press="{!c.buttonClick}" class="slds-button slds-button--neutral" />
</aura:component>

controller:
({
    buttonClick : function(component, event, helper) {
         $A.get('e.force:refreshView').fire();
    },
    refreshData : function(component, event, helper) {
        alert('Contact data refreshed');
    }
})

The other components simply have the alert text change to reflect the location of the component.
Before we turn this on in production (which you cannot turn back off), we just wanted to verify that our current deployment process that using the Migration Tool will not be affected.

We assume we can use both Salesforce DX and the Migration Tool at the same time but wanted to verify that assumption before making this irrevocable decision.
I have a lightning component that shows a contact's files and attachments. It works fine in my normal sandbox but when I drop it into a Communities page, it shows nothing. I see references to giving users the "View Content in Portal" permission to allow access in Portal ALL OVER THE PLACE, but I have some questions about that:

1. I cannot find the "View Content in Portal" permission anywhere. WHERE IS IT?
2. Are Communities and Portal the same thing or at least do they use the same permission settings?
3. If I find this elusive setting and turn it on, will it allow me to query the ContentDocumentLink, Document, and Attachment objects for a Community user?
4. If I want to allow them to upload their own documents, what are the licensing implications?


Thanks,
Vance
Ever since Winter 17 was pushed to our sandboxes, all of them have gone from taking about 20-30 minutes to deploy using the Migration Tool to taking up to 2.5 hours and typically 1.5 hours!! A simple retrieve operation takes a minimum of 10 minutes.

Even saving single files (either through DevConsole or Welkin) ranges from taking 4 seconds to 11 MINUTES!!! Yes, 11 minutes. It has happened twice on the same file that also took 4 seconds on a different save. It is very common to see save times of 3-4 minutes.

This IS KILLING OUR PRODUCTIVITY!!!

Has anyone else noticed slowness related to Winter 17 deployments?
 
Now that Winter 17 has been pushed we are getting the following error using the Migration Tool (Ant):
 
FormFactors is required for Lightning apps

Is anyone else seeing this? Anyone know how to fix it?
When I go into Setup in Lightning in Chrome it will load the setup page and then I can expand the menu items on the left (users, Custom Code, etc) but as soon as I click on a settings page (ANY PAGE) that tab locks up completely and never comes back. Setup works fine in IE or Firefox.

I have disabled all extensions but that didn't help.

Is anyone else seeing this or has anyone seen this and fixed it before?
I have some flows that call Apex code (@InvocableMethod). There is a VERY extremely annoying problem that EVERY TIME I save my class or deploy the flow, it SILENTLY STRIPS OUT CALLS TO MY CODE!!! It does not do this to all calls to Apex, just some of them. But it does it VERY consistently on those.

Is Process Builder just not ready for calling out to Apex Code yet?

I have found no workarounds for this bug.
I was frustrated with the various answers I had found as to how to get a complete mapping of dependent picklist values, so I combined a few different posts into a solution that works, is efficient, and does not require a web service call. This only works for single level dependencies,

I created a class called Utilities that holds the method GetDependentOptions for getting dependent picklist values. There is also a method called GetPickListValues to retrieve values for a simple picklist. The method FirstControllingValueFor is used to do a reverse lookup given a child value to find the first controlling value that the child is valid for.

public class Utilities {
    public static List<String> GetPickListValues(String object_name, String field_name, String first_val) {
        SObjectType objectType = Schema.getGlobalDescribe().get(object_name);
        List<String> options = new List<String>(); //new list for holding all of the picklist options
        if (first_val != null) { //if there is a first value being provided
            options.add(first_val); //add the first option
        }
        List<String> classes = new List<String>();
        classes.add(object_name);
        List<Schema.DescribeSObjectResult> results = Schema.describeSObjects(classes);
        Schema.DescribeSObjectResult sobject_describe = results[0];
        Map<String, Schema.SObjectField> field_map = sobject_describe.fields.getMap(); //get a map of fields for the passed sobject
        if (null != field_map) {
            Schema.SObjectField fs = field_map.get(field_name);
            Schema.DescribeFieldResult dsr = fs.getDescribe();
            if (null != dsr) {
                List<Schema.PicklistEntry> pick_list_values = dsr.getPickListValues(); //grab the list of picklist values for the passed field on the sobject
                if (null != pick_list_values) {
                    for (Schema.PicklistEntry a : pick_list_values) { //for all values in the picklist list            
                        options.add(a.getValue());
                    }
                }
            }
        }
        return options; //return the List
    }
    
    private static Map<String, Integer> base64Vals = null;
    
    private static List<Integer> ConvertB64ToInts(string b64Str) {
        if (base64Vals == null) {
            base64Vals = new Map<String, Integer> {
                'A'=>00,'B'=>01,'C'=>02,'D'=>03,'E'=>04,'F'=>05,'G'=>06,'H'=>07,'I'=>08,'J'=>09,
                'K'=>10,'L'=>11,'M'=>12,'N'=>13,'O'=>14,'P'=>15,'Q'=>16,'R'=>17,'S'=>18,'T'=>19,
                'U'=>20,'V'=>21,'W'=>22,'X'=>23,'Y'=>24,'Z'=>25,'a'=>26,'b'=>27,'c'=>28,'d'=>29,
                'e'=>30,'f'=>31,'g'=>32,'h'=>33,'i'=>34,'j'=>35,'k'=>36,'l'=>37,'m'=>38,'n'=>39,
                'o'=>40,'p'=>41,'q'=>42,'r'=>43,'s'=>44,'t'=>45,'u'=>46,'v'=>47,'w'=>48,'x'=>49,
                'y'=>50,'z'=>51,'0'=>52,'1'=>53,'2'=>54,'3'=>55,'4'=>56,'5'=>57,'6'=>58,'7'=>59,
                '8'=>60,'9'=>61,'+'=>62,'/'=>63
            };
        }
        List<Integer> ints = new List<Integer>();
        for (Integer idx = 0; idx< b64Str.length(); ++idx) {
            String c = String.fromCharArray(new List<Integer> { b64Str.charAt(idx)});
            ints.add(base64Vals.get(c));
        }
        return ints;
    }

    private class TPicklistEntry{
        public string active {get;set;}
        public string defaultValue {get;set;}
        public string label {get;set;}
        public string value {get;set;}
        public string validFor {get;set;}
        public TPicklistEntry(){}
    }

    public static Map<String,List<String>> GetDependentOptions(String pObjName, String pControllingFieldName, String pDependentFieldName) {
        Map<String,List<String>> mapResults = new Map<String,List<String>>();

        //verify/get object schema
        Schema.SObjectType pType = Schema.getGlobalDescribe().get(pObjName);
        if ( pType == null ) return mapResults;
        Map<String, Schema.SObjectField> objFieldMap = pType.getDescribe().fields.getMap();

        //verify field names
        if (!objFieldMap.containsKey(pControllingFieldName) || !objFieldMap.containsKey(pDependentFieldName)) return mapResults;

        //get the control & dependent values
        List<Schema.PicklistEntry> ctrl_ple = objFieldMap.get(pControllingFieldName).getDescribe().getPicklistValues();
        List<Schema.PicklistEntry> dep_ple = objFieldMap.get(pDependentFieldName).getDescribe().getPicklistValues();

        //initialize results mapping
        for(Integer pControllingIndex=0; pControllingIndex < ctrl_ple.size(); pControllingIndex++) {
            mapResults.put( ctrl_ple[pControllingIndex].getLabel(), new List<String>());
        }

        //serialize dep entries
        List<TPicklistEntry> objDS_Entries = new List<TPicklistEntry>();
        objDS_Entries = (List<TPicklistEntry>)JSON.deserialize(JSON.serialize(dep_ple), List<TPicklistEntry>.class);

        for (TPicklistEntry objDepPLE : objDS_Entries){
            List<Integer> bitValues = ConvertB64ToInts(objDepPLE.validFor);

            Integer bitMask = 32; // Ignore highest 2 bits
            Integer intIndex = 0;
            Integer bitIdx = 0;
            for (Integer numBits = bitValues.size() * 6; numBits > 0; --numBits) {
                Integer bits = bitValues[intIndex];
                if ((bits & bitMask) == bitMask) {
                    mapResults.get( ctrl_ple[bitIdx].getLabel() ).add( objDepPLE.label );
                }
                bitMask = bitMask >>> 1;
                ++bitIdx;

                if (bitMask == 0) {
                    bitMask = 32;
                    intIndex = intIndex + 1;
                }
            }
        }
        return mapResults;
    }//GetDependentOptions
   
    public static String FirstControllingValueFor(String pObjName, String pControllingFieldName, String pDependentFieldName, String childValue) {
        Map<String,List<String>> mappedItems = GetDependentOptions(pObjName, pControllingFieldName, pDependentFieldName);
        for (String key : mappedItems.keySet()) {
            List<String> items = mappedItems.get(key);
            Set<String> itemSet = new Set<String>(items);
            if (itemSet.contains(childValue)) {
                return key;
            }
        }
        return null;
    }
}
I have a column that is a multi-select picklist. I would like to translate the semi-colons returned from SOQL to spaces before I display this value. How would I replace all the ';' with spaces?

Here is the part of my page that displays this column
        <aura:iteration items="{!v.territories}" var="t">
            <tr>
                <td>{!t.States__c}</td>
            </tr>
        </aura:iteration>

This currently looks like "AK;AL;AR;AZ;CA;CT;CT;DE;FL;GA;HI;IA;ID;IL;IN;KY"  which does not wrap well.
WInter 19 had the following change:
The label attribute now supports text only. Previously the label supported a component type, and you could include, for example, an icon in the tab’s label. If you use a component in a lighting:tab label now, only the text portion of the label value displays. Any CSS classes that are applied are ignored.

The result is that I can no longer add classes to the tab. The following code no longer adds completed to the class attribute:
<lightning:tab id="Calendar" label="Calendar" class="{!v.CalendarHasSaved ? 'completed' : ''}">
Even if I have class="completed" it strips it out.

Why did they need to do this? I had styling that indicated whether a tab was 'complete' which no longer works.
I noticed that components respond to the force:refreshView event long after they have been removed from view. I wrote some test components that I placed on the Contact, Account, and Opportunity related list pages. If I navigate to a record of each type, they all continue to respond to the refreshView event. In fact, if I navigate to different accounts or contacts, each one continues to repsond to the refreshView event. I have found that it keeps a maximum of 4 components active in the background before actually destroying (unrendering) them.

In some components, we reload data on the refreshView event. Is there a way to know that reload of data is a waste of time?

Here is my test contact component:
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes">
    <aura:handler event="force:refreshView" action="{!c.refreshData}" />
    <ui:button label="Fire" press="{!c.buttonClick}" class="slds-button slds-button--neutral" />
</aura:component>

controller:
({
    buttonClick : function(component, event, helper) {
         $A.get('e.force:refreshView').fire();
    },
    refreshData : function(component, event, helper) {
        alert('Contact data refreshed');
    }
})

The other components simply have the alert text change to reflect the location of the component.
Before we turn this on in production (which you cannot turn back off), we just wanted to verify that our current deployment process that using the Migration Tool will not be affected.

We assume we can use both Salesforce DX and the Migration Tool at the same time but wanted to verify that assumption before making this irrevocable decision.
I have a lightning component that shows a contact's files and attachments. It works fine in my normal sandbox but when I drop it into a Communities page, it shows nothing. I see references to giving users the "View Content in Portal" permission to allow access in Portal ALL OVER THE PLACE, but I have some questions about that:

1. I cannot find the "View Content in Portal" permission anywhere. WHERE IS IT?
2. Are Communities and Portal the same thing or at least do they use the same permission settings?
3. If I find this elusive setting and turn it on, will it allow me to query the ContentDocumentLink, Document, and Attachment objects for a Community user?
4. If I want to allow them to upload their own documents, what are the licensing implications?


Thanks,
Vance
Now that Winter 17 has been pushed we are getting the following error using the Migration Tool (Ant):
 
FormFactors is required for Lightning apps

Is anyone else seeing this? Anyone know how to fix it?
When I go into Setup in Lightning in Chrome it will load the setup page and then I can expand the menu items on the left (users, Custom Code, etc) but as soon as I click on a settings page (ANY PAGE) that tab locks up completely and never comes back. Setup works fine in IE or Firefox.

I have disabled all extensions but that didn't help.

Is anyone else seeing this or has anyone seen this and fixed it before?
I was frustrated with the various answers I had found as to how to get a complete mapping of dependent picklist values, so I combined a few different posts into a solution that works, is efficient, and does not require a web service call. This only works for single level dependencies,

I created a class called Utilities that holds the method GetDependentOptions for getting dependent picklist values. There is also a method called GetPickListValues to retrieve values for a simple picklist. The method FirstControllingValueFor is used to do a reverse lookup given a child value to find the first controlling value that the child is valid for.

public class Utilities {
    public static List<String> GetPickListValues(String object_name, String field_name, String first_val) {
        SObjectType objectType = Schema.getGlobalDescribe().get(object_name);
        List<String> options = new List<String>(); //new list for holding all of the picklist options
        if (first_val != null) { //if there is a first value being provided
            options.add(first_val); //add the first option
        }
        List<String> classes = new List<String>();
        classes.add(object_name);
        List<Schema.DescribeSObjectResult> results = Schema.describeSObjects(classes);
        Schema.DescribeSObjectResult sobject_describe = results[0];
        Map<String, Schema.SObjectField> field_map = sobject_describe.fields.getMap(); //get a map of fields for the passed sobject
        if (null != field_map) {
            Schema.SObjectField fs = field_map.get(field_name);
            Schema.DescribeFieldResult dsr = fs.getDescribe();
            if (null != dsr) {
                List<Schema.PicklistEntry> pick_list_values = dsr.getPickListValues(); //grab the list of picklist values for the passed field on the sobject
                if (null != pick_list_values) {
                    for (Schema.PicklistEntry a : pick_list_values) { //for all values in the picklist list            
                        options.add(a.getValue());
                    }
                }
            }
        }
        return options; //return the List
    }
    
    private static Map<String, Integer> base64Vals = null;
    
    private static List<Integer> ConvertB64ToInts(string b64Str) {
        if (base64Vals == null) {
            base64Vals = new Map<String, Integer> {
                'A'=>00,'B'=>01,'C'=>02,'D'=>03,'E'=>04,'F'=>05,'G'=>06,'H'=>07,'I'=>08,'J'=>09,
                'K'=>10,'L'=>11,'M'=>12,'N'=>13,'O'=>14,'P'=>15,'Q'=>16,'R'=>17,'S'=>18,'T'=>19,
                'U'=>20,'V'=>21,'W'=>22,'X'=>23,'Y'=>24,'Z'=>25,'a'=>26,'b'=>27,'c'=>28,'d'=>29,
                'e'=>30,'f'=>31,'g'=>32,'h'=>33,'i'=>34,'j'=>35,'k'=>36,'l'=>37,'m'=>38,'n'=>39,
                'o'=>40,'p'=>41,'q'=>42,'r'=>43,'s'=>44,'t'=>45,'u'=>46,'v'=>47,'w'=>48,'x'=>49,
                'y'=>50,'z'=>51,'0'=>52,'1'=>53,'2'=>54,'3'=>55,'4'=>56,'5'=>57,'6'=>58,'7'=>59,
                '8'=>60,'9'=>61,'+'=>62,'/'=>63
            };
        }
        List<Integer> ints = new List<Integer>();
        for (Integer idx = 0; idx< b64Str.length(); ++idx) {
            String c = String.fromCharArray(new List<Integer> { b64Str.charAt(idx)});
            ints.add(base64Vals.get(c));
        }
        return ints;
    }

    private class TPicklistEntry{
        public string active {get;set;}
        public string defaultValue {get;set;}
        public string label {get;set;}
        public string value {get;set;}
        public string validFor {get;set;}
        public TPicklistEntry(){}
    }

    public static Map<String,List<String>> GetDependentOptions(String pObjName, String pControllingFieldName, String pDependentFieldName) {
        Map<String,List<String>> mapResults = new Map<String,List<String>>();

        //verify/get object schema
        Schema.SObjectType pType = Schema.getGlobalDescribe().get(pObjName);
        if ( pType == null ) return mapResults;
        Map<String, Schema.SObjectField> objFieldMap = pType.getDescribe().fields.getMap();

        //verify field names
        if (!objFieldMap.containsKey(pControllingFieldName) || !objFieldMap.containsKey(pDependentFieldName)) return mapResults;

        //get the control & dependent values
        List<Schema.PicklistEntry> ctrl_ple = objFieldMap.get(pControllingFieldName).getDescribe().getPicklistValues();
        List<Schema.PicklistEntry> dep_ple = objFieldMap.get(pDependentFieldName).getDescribe().getPicklistValues();

        //initialize results mapping
        for(Integer pControllingIndex=0; pControllingIndex < ctrl_ple.size(); pControllingIndex++) {
            mapResults.put( ctrl_ple[pControllingIndex].getLabel(), new List<String>());
        }

        //serialize dep entries
        List<TPicklistEntry> objDS_Entries = new List<TPicklistEntry>();
        objDS_Entries = (List<TPicklistEntry>)JSON.deserialize(JSON.serialize(dep_ple), List<TPicklistEntry>.class);

        for (TPicklistEntry objDepPLE : objDS_Entries){
            List<Integer> bitValues = ConvertB64ToInts(objDepPLE.validFor);

            Integer bitMask = 32; // Ignore highest 2 bits
            Integer intIndex = 0;
            Integer bitIdx = 0;
            for (Integer numBits = bitValues.size() * 6; numBits > 0; --numBits) {
                Integer bits = bitValues[intIndex];
                if ((bits & bitMask) == bitMask) {
                    mapResults.get( ctrl_ple[bitIdx].getLabel() ).add( objDepPLE.label );
                }
                bitMask = bitMask >>> 1;
                ++bitIdx;

                if (bitMask == 0) {
                    bitMask = 32;
                    intIndex = intIndex + 1;
                }
            }
        }
        return mapResults;
    }//GetDependentOptions
   
    public static String FirstControllingValueFor(String pObjName, String pControllingFieldName, String pDependentFieldName, String childValue) {
        Map<String,List<String>> mappedItems = GetDependentOptions(pObjName, pControllingFieldName, pDependentFieldName);
        for (String key : mappedItems.keySet()) {
            List<String> items = mappedItems.get(key);
            Set<String> itemSet = new Set<String>(items);
            if (itemSet.contains(childValue)) {
                return key;
            }
        }
        return null;
    }
}
I have a column that is a multi-select picklist. I would like to translate the semi-colons returned from SOQL to spaces before I display this value. How would I replace all the ';' with spaces?

Here is the part of my page that displays this column
        <aura:iteration items="{!v.territories}" var="t">
            <tr>
                <td>{!t.States__c}</td>
            </tr>
        </aura:iteration>

This currently looks like "AK;AL;AR;AZ;CA;CT;CT;DE;FL;GA;HI;IA;ID;IL;IN;KY"  which does not wrap well.
Hi,

Is there a way to access the trusted IP ranges through Apex and SOQL? I'm creating a visualforce application that checks if the user has specific Ip ranges set.

Thanks,
Andrew