+ Start a Discussion
Artem Kalus 7Artem Kalus 7 
I have a visualforce page, that implemnts lightningStyleSheets="true" and has apex:tabPanel with multiple tabs. When user is in Lightnig Experience and any button is pressed on the same page, which causes a component rerendering, tabs styling changes to classic.

VF PAGE:
<apex:page controller="PracticeCompGrid_Cont" showHeader="true" lightningStylesheets="true">
            
    <!-- Create Tab panel -->
    <apex:tabPanel switchType="client" selectedTab="name2" id="AccountTabPanel"
        tabClass="activeTab" inactiveTabClass="inactiveTab">
        <apex:tab label="One" name="name1" id="tabOne">content for tab one</apex:tab>
        <apex:tab label="Two" name="name2" id="tabTwo">
                            
            <apex:pageBlock id="pbId">

                <apex:pageBlockButtons >
                    <apex:form >
                        <apex:commandButton action="{!debugFun}" rerender="pbId" value="Test" />
                    </apex:form>
                </apex:pageBlockButtons>
                <apex:pageBlockTable value="{!accList}" var="a">
                    <apex:column value="{!a.Name}" />
                </apex:pageBlockTable>
            </apex:pageBlock>
        </apex:tab>
    </apex:tabPanel>
</apex:page>

CONTROLLER:
public class PracticeCompGrid_Cont {

    public List <Account> accList {get;set;}
    
    public PracticeCompGrid_Cont (){
        accList = [SELECT Name FROM Account LIMIT 10];
    }
    
    public void debugFun(){
        System.debug('Acc: '+accList);
    }
}

BEFORE BUTTON IS PRESSED:
User-added image
AFTER BUTTON IS PRESSED AND RERENDER HAPPENED:
User-added image



Has anyone seen this before? If yes, any solutions?
Best Answer chosen by Artem Kalus 7
Dushyant SonwarDushyant Sonwar
Hi Artem ,

Your component is using a output  tag which is a html 5 tag .  When you rerender the pageblock , tag disappears from your html.
You need to set a doctype , so that your output tag does not disappears.
<apex:page controller="PracticeCompGrid_Cont" showHeader="true" doctype="html-5.0" lightningStylesheets="true">


Final Code will be something like this below :
<apex:page controller="PracticeCompGrid_Cont" showHeader="true" doctype="html-5.0" lightningStylesheets="true">
     
    <style>
        body .rich-tabhdr-cell-active, .slds-scope .rich-tabhdr-cell-active {
        border-bottom-color: #0070d2 !important;
        font-weight: 700 !important;
        color: #3e3e3c !important;
        }
        .rich-tab-active  , .rich-tab-inactive , .rich-tabpanel-content {
        background-image: none;
        background-color: transparent;
        border-style: none;
        }
        .rich-tabpanel-content {
            color : none !important;
        }
    </style>
    <apex:form >
    <!-- Create Tab panel -->   
    <apex:tabPanel switchType="client" selectedTab="name2" id="AccountTabPanel"
                   tabClass="activeTab" inactiveTabClass="inactiveTab">
        <apex:tab label="One" name="name1" id="tabOne">content for tab one</apex:tab>
        <apex:tab label="Two" name="name2" id="tabTwo">
            
            <apex:pageBlock id="pbId">
                
                <apex:pageBlockButtons >
                   
                        <apex:commandButton action="{!debugFun}" rerender="pbId" value="Test" oncomplete="loadSliderScript();"/>
                    
                </apex:pageBlockButtons>
                <apex:pageBlockTable value="{!wrList}" var="w" style="font-size:13px;font-family : 'Salesforce Sans', Arial, sans-serif">
                    <apex:column >
                        <c:PracticeSliderComponent num="{!w.ind}"/>
                    </apex:column>
                    <apex:column value="{!w.a.Name}" />
                </apex:pageBlockTable>
            </apex:pageBlock>
        </apex:tab>
        
    </apex:tabPanel>
    
    
    </apex:form>
</apex:page>

 
Susan ThomlinsonSusan Thomlinson 
I am having issues with Creating  an Apex class that returns Account objects for the Mapping.net concepts challenge.  I am a VB and Javascript programmer and I can't seem to get the syntax right.   
public class AccountUtils {
    
    public static void accountsByState(String st){
       List<String> accts = [SELECT Id, Name FROM Account WHERE billingState = :st];
 }
  
}
I believe the first part is correct, but I cannot seem to get a return value.  I am confused by the constructors.  I have tried the documentation but I can't get a return value.  Please help.  I need to get this challenge complete.
 
Best Answer chosen by Susan Thomlinson
Mahesh DMahesh D
Hi Susan,

You can try this:
 
public class AccountUtils {
    public static List<Account> accountsByState(String st){
       List<Account> acctList = [SELECT Id, Name FROM Account WHERE billingState = :st];
	   return acctList;
	}
}


Please look into the below useful links:

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_defining_methods.htm

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_static.htm

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_defining.htm

http://www.tutorialspoint.com/apex/apex_methods.htm

Please do let me know if it helps you.

Regards,
Mahesh
David White 41David White 41 
I can't pass step 2 of the App Customization Superbadge with the following error: 

Challenge Not yet complete... here's what's wrong: 
There was an unexpected error in your org which is preventing this assessment check from completing: System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Desired_of_Volunteers__c]: [Desired_of_Volunteers__c].

The field does exist. Have spent the morning reviewing all fields making sure they are setup correct. Thanks for any input.
User-added image
Best Answer chosen by David White 41
Raj VakatiRaj Vakati
Make sure your profile is having access for this field ?
If its dnt work , create a new playground org and try to resolve 
Charles Cummings 7Charles Cummings 7 
Hi, I'm starting a specific post for this topic. 

I'm getting the following message on step 9. 

Challenge Not yet complete... here's what's wrong: 
The 'Opp Stage by Adventure' report does not appear to be configured correctly. Make sure it has the correct report type, groupings, filters and chart type.

It is ironic to get to the end and get stuck on charts which I do all the time. :) Ok, here are the instructions:

Give sales reps a visual indicator to compare product performance. First, create a summary report on opportunities named Opp Stage by Adventure. Filter it by Product Date within the past year. For the purpose of this superbadge, assume this date range is 1/1/2026-12/31/2026. Second, add a stacked vertical bar chart of the number of explorers by product name, grouped by stage, to your summary report. Finally, add this chart to your Lightning Adventure Record Page with the label Adventure Stage Comparison. To ensure that this chart isn’t accidentally displayed to customers, add it to a new section called Adventure Comparison.

And, here is what I have. 

I have a Summary Report of "Opportunities with Adventures". In the data model, each Opportunnity corresponds to 1 Explorer from what I can tell per the data model. I've grouped the report by adventure and stage. I have not grouped by Explorer (which is a Contact Role on each Opportunity). I have tried that though and still got the same error. Note also that I'm using "Adventure Date" instead of Procuct Date per the instructions since Product has been renamed to Adventure. 

Opp Stage by Adventure Report



Chart Editor

In the Lightning Record page for Adventure, I've created a custom tab called "Adventure Comparison" and added in the chart called " Adventure Stage Comparison". I've also tried flipping those names, but I still got the same error. 

Adventure Chart in Lightning Record

Any hints would be appreciated. :)
Best Answer chosen by Charles Cummings 7
sfdcFanBoysfdcFanBoy
oh oh, almost there!

You need to group by Stage first and then the Adventure Name.  

Let me know if that helps.  Cheers!
L0bster1L0bster1 

I want to automatically convert new leads into contacts. I have a trigger on Lead after update that will bulk convert 100 leads at a time. The problem I have  is that my marketing automation tool pushes new leads into Salesforce in batches of 200 at a time. When I try to import 200 leads, the bulk convert fails due to a too many DML 151 error.

 

I read that the convertlead function can only handle 100 records at a time. How can I edit the code to handle 200 imports at a time? Is it possible?

 

Thanks in advance.

 

trigger AutoConvert on Lead (after update) {

for(Lead myLead: Trigger.new){ if(Trigger.new[0].isConverted == false) { Database.LeadConvert lc = new database.LeadConvert(); lc.setLeadId(myLead.Id); lc.convertedStatus = 'Qualified'; //Database.ConvertLead(lc,true); lc.setDoNotCreateOpportunity(true); Database.LeadConvertResult lcr = Database.convertLead(lc); System.assert(lcr.isSuccess()); }}}

 

Best Answer chosen by Admin (Salesforce Developers) 
Jerun JoseJerun Jose

Instead of passing one lead value at a time to the convertLead method, you can pass a list of lead values. From the documentation at

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_dml_convertLead.htm
you can do something like

LeadConvertResult[] Database.convertLead(LeadConvert[] leadsToConvert, Boolean opt_allOrNone)

 

Also, you trigger is not designed for bulk operations. Use the updated trigger below and modify it as necessary.

 

trigger AutoConvert on Lead (after update) {
	list<Lead> LeadsToConvert = new list<Lead>();
	for(Lead myLead: Trigger.new){
		if(!myLead.isConverted)
			LeadsToConvert.add(myLead);
	}

	list<Database.LeadConvert> leadConverts = new list<Database.LeadConvert>();
	for(Lead myLead : LeadsToConvert){
		Database.LeadConvert lc = new database.LeadConvert();
		lc.setLeadId(myLead.Id);
		lc.convertedStatus = 'Qualified';
		//Database.ConvertLead(lc,true);
		lc.setDoNotCreateOpportunity(true);
		leadConverts.add(lc);
	}

	if(!leadConverts.isEmpty()){
		for(Integer i = 0; i <= leadConverts.size()/100 ; i++){
			list<Database.LeadConvert> tempList = new list<Database.LeadConvert>();
			Integer startIndex = i*100;
			Integer endIndex = ((startIndex+100) < leadConverts.size()) ? startIndex+100: leadConverts.size();
			for(Integer j=startIndex;j<endIndex;j++){
				tempList.add(leadConverts[j]);
			}
			Database.LeadConvertResult[] lcrList = Database.convertLead(tempList, false);
			for(Database.LeadConvertResult lcr : lcrList)
				System.assert(lcr.isSuccess());
		}
	}
}

 

 Edit - forgot the part about max 100 records for convertLead. Updated the apex code for it

Shobhit SaxenaShobhit Saxena 
The campingList JavaScript controller isn't setting the 'item' as a parameter or saving the record correctly.

My code is as follows:

1---Camping List Component
<aura:component controller="CampingListController">
	
    <aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
    
    <aura:handler name="addItem" event="c:addItemEvent"
   	action="{!c.handleAddItem }"/>
    
    <aura:attribute name="newItem" type="Camping_Item__c"
     default="{ 'sobjectType': 'Camping_Item__c',
                    'Name': '',
                    'Quantity__c': 0,
                    'Price__c': 0,
                    'Packed__c': false }"/>
    
    <aura:attribute name="items" type="Camping_Item__c[]"/>
    
    <ol>
    <li>Bug Spray</li>
    <li>Bear Repellant</li>
    <li>Goat Food</li>
    </ol>
    
       <!-- NEW EXPENSE FORM -->
    <div class="slds-col slds-col--padded slds-p-top--large">

        <c:campingListForm/>

    </div>
    <!-- / NEW EXPENSE FORM -->    
   

    <div class="slds-card slds-p-top--medium">
        <header class="slds-card__header">
            <h3 class="slds-text-heading--small">Items</h3>
        </header>
        
        <section class="slds-card__body">
            <div id="list" class="row">
                <aura:iteration items="{!v.items}" var="items">
                    <c:campingListItem item="{!item}"/>
                </aura:iteration>
            </div>
        </section>
    </div>

</aura:component>

2---Camping List Controller
 
({
    // Load items from Salesforce
	doInit: function(component, event, helper) {

    // Create the action
    var action = component.get("c.getItems");

    // Add callback behavior for when response is received
    action.setCallback(this, function(response) {
        var state = response.getState();
        if (component.isValid() && state === "SUCCESS") {
            component.set("v.items", response.getReturnValue());
        }
        else {
            console.log("Failed with state: " + state);
        }
    });

    // Send action off to be executed
    $A.enqueueAction(action);
},

    
    handleAddItem: function(component, event, helper) {
    var newItem = event.getParam("item");
    //helper.createItem(component, newItem);
        this.saveItem(component, item, function(response){
        var state = response.getState();
        if (component.isValid() && state === "SUCCESS") {
            var items = component.get("v.items");
            items.push(response.getReturnValue());
            component.set("v.items", items);
        }
    }
          
}
                      
})

3---Camping List Helper

Empty

4---Camping List Form
 
<aura:component >
	
    <aura:registerEvent name="addItem" type="c:addItemEvent"/>
        <!-- CREATE NEW ITEM FORM -->
    <form class="slds-form--stacked">

      <div class="slds-form-element slds-is-required">
          <div class="slds-form-element__control">
              <ui:inputText aura:id="itemname" label="Name"
                  class="slds-input"
                  labelClass="slds-form-element__label"
                  value="{!v.newItem.Name}"
                  required="true"/>

          </div>
     </div>

     <div class="slds-form-element slds-is-required">
          <div class="slds-form-element__control">
              <ui:inputNumber aura:id="quantity" label="Quantity"
                  class="slds-input"
                  labelClass="slds-form-element__label"
                  value="{!v.newItem.Quantity__c}"
                  required="true"/>

          </div>
      </div>

      <div class="slds-form-element">
          <div class="slds-form-element__control">
              <ui:inputCurrency aura:id="price" label="Price"
                  class="slds-input"
                  labelClass="slds-form-element__label"
                  value="{!v.newItem.Price__c}"
                  />
          </div>
      </div>

      <div class="slds-form-element">
          <ui:inputCheckbox aura:id="packed" label="Packed?"
              class="slds-checkbox"
              labelClass="slds-form-element__label"
              value="{!v.newItem.Packed__c}"/>
      </div>

      <div class="slds-form-element">
          <ui:button label="Create Camping Item"
              class="slds-button slds-button--brand"
              press="{!c.clickCreateItem}"/>
      </div>

    </form>
    <!-- / CREATE NEW ITEM FORM -->
</aura:component>

5---CampingListFormController
 
({
    
    clickCreateItem: function(component, event, helper) {    
    if(helper.validateItemForm(component)){
        // Create the new item
        var newItem = component.get("v.newItem");
        helper.createItem(component, newItem);
    }
        
        }

})

6---CampingListFormHelper
 
({
 createItem: function(component, newItem) {
    var createItem = component.getItem("createItem");
    createItem.setParams({ "item": item });
    createItem.fire();
             component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c',
                    'Name': '',
                    'Quantity__c': 0,
                    'Price__c': 0,
                    'Packed__c': false }/>);
},
    

		validateItemForm: function(component) {
		
              // Simplistic error checking
        var validItem = true;

        // Name must not be blank
        var nameField = component.find("itemname");
        var itemname = nameField.get("v.value");
        if ($A.util.isEmpty(itemname)){
            validItem = false;
            nameField.set("v.errors", [{message:"Item name can't be blank."}]);
        }
        else {
            nameField.set("v.errors", null);
        }
        
        // Quantity must not be blank
        var quantityField = component.find("quantity");
        var quantity = nameField.get("v.value");
        if ($A.util.isEmpty(quantity)){
            validItem = false;
            quantityField.set("v.errors", [{message:"Quantity can't be blank."}]);
        }
        else {
            quantityField.set("v.errors", null);
        }
		// Price must not be blank
        var priceField = component.find("price");
        var price = priceField.get("v.value");
        if ($A.util.isEmpty(price)){
            validItem = false;
            priceField.set("v.errors", [{message:"Price can't be blank."}]);
        }
        else {
            quantityField.set("v.errors", null);
        }
            return validItem;

	}
})

I am still getting this error:

User-added image

Any help would be appreciated.
 
Best Answer chosen by Shobhit Saxena
John Lay 9John Lay 9
See if this help for saving in the handleAddItem....
 
var action = component.get("c.saveItem");
    		action.setParams({"item": newItem});
    		action.setCallback(this, function(response){
        		var state = response.getState();
        		if (component.isValid() && state === "SUCCESS") {
            		// all good, nothing to do.
        		}
    		});
    		$A.enqueueAction(action);

 
Joe Rodden 7Joe Rodden 7 
Fairly new so bear with me. I've written a class that throws an error message for any duplicate emails on Contacts. While writing the test I thought I'd covered everything the original class does however I'm only ending up with 85% code coverage. I'd like to figure out how to get to 100. 

Class (the lines that aren't covered are bolded and underlined):
 
public class Contact_CheckEmail {

    List<Contact> contacts = new List<Contact>();
    
    public Contact_CheckEmail(List<Contact> trigCon){
       contacts = trigCon; 
    }
    

    public void checkEmail(){
    Set<String> emailSet = new Set<String>();
    
    for(Contact c : contacts){
        
        emailSet.add(c.Email);
    
    }
    
    List<Contact> duplicateEmail = [SELECT Email FROM Contact WHERE Email IN: emailSet];
    
    Set<String> duplicateEmailId = new Set<String>();
    
    for(Contact c : duplicateEmail) {
    
        duplicateEmailId.add(c.Email);
    
    }

    for(Contact c: contacts){
        if(duplicateEmailId.contains(c.Email)){
               c.addError('Email already exists.');
        
        }
    
    }
    
}
}


Test Class:
@isTest
public class Test_CheckEmail {
    
    @isTest static void EmailCheckTest(){
        
        Account acc = new Account();
        acc.Name = 'TestAccount';
        insert acc;
        
        List<Contact> contacts = new List<Contact>();
        for( Integer i = 0;i < 1; i++){
            String iString = String.valueof(i);
            Contact myCon = new Contact();
            myCon.LastName = 'iString';
            myCon.AccountId = acc.Id;
            myCon.Email = 'fakeman@fake.com';
            contacts.add(myCon);
        }
        
        try{
        insert contacts;
        }
        catch (Exception e){
            Boolean expectedException = e.getMessage().contains('Email already exists.') ? true : false;
            System.assertEquals(expectedException, true);
        }
        
        List<Contact> contacts2 = new List<Contact>();
        for( Integer i = 0;i < 1; i++){
            String iString = String.valueof(i);
            Contact myCon = new Contact();
            myCon.LastName = 'iString';
            myCon.AccountId = acc.Id;
            myCon.Email = iString + '@fake.com';
            contacts2.add(myCon);
        }
        
        try{
        insert contacts2;
        }
        catch (Exception e){
            Boolean expectedException = e.getMessage().contains('Email already exists.') ? true : false;
            System.assertEquals(expectedException, false);
        }
        
        
        
    }

}

 
Best Answer chosen by Joe Rodden 7
Khan AnasKhan Anas (Salesforce Developers) 
Hi Joe,

Greetings to you!

Please use the below code, I have checked in my org and it is covering 100%
 
@isTest
public class Test_CheckEmail {
    
    @isTest static void EmailCheckTest(){        
        Account acc = new Account();
        acc.Name = 'TestAccount';
        insert acc;
        
        List<Contact> contacts = new List<Contact>();
        for( Integer i = 0;i < 1; i++){
            String iString = String.valueof(i);
            Contact myCon = new Contact();
            myCon.LastName = 'iString';
            myCon.AccountId = acc.Id;
            myCon.Email = 'fakeman@fake.com';
            contacts.add(myCon);
        }
        
        try{
            insert contacts;
        }
        catch (Exception e){
            Boolean expectedException = e.getMessage().contains('Email already exists.') ? true : false;
            System.assertEquals(expectedException, true);
        }
        
        List<Contact> contacts2 = new List<Contact>();
        for( Integer i = 0;i < 1; i++){
            String iString = String.valueof(i);
            Contact myCon = new Contact();
            myCon.LastName = 'iString';
            myCon.AccountId = acc.Id;
            myCon.Email = iString + '@fake.com';
            contacts2.add(myCon);
        }
        
        try{
            insert contacts2;
        }
        catch (Exception e){
            Boolean expectedException = e.getMessage().contains('Email already exists.') ? true : false;
            System.assertEquals(expectedException, false);
        }
        
        Contact_CheckEmail cce = new Contact_CheckEmail(contacts2);
        cce.checkEmail();
    }
}


I hope it helps you.

Kindly let me know if it helps you and close your query by marking it as solved so that it can help others in the future.

Thanks and Regards,
Khan Anas
Raghu Sharma 6Raghu Sharma 6 
In which scenarios should we put the logic in apex controller vs java script controller

For eg: For making salesforce SOQL/DML statements, we can put the logic apex controller. Similarly, where should be put the logic for REST API calls? When should we use apex controller? Whar are the best practices
Best Answer chosen by Raghu Sharma 6
Rahul KumarRahul Kumar (Salesforce Developers) 
Hi Raghu,

Create a server-side controller in Apex and use the @AuraEnabled annotation to enable access to the controller method.
Only methods that you have explicitly annotated with @AuraEnabled are exposed. Calling server-side actions aren’t counted against your org’s API limits. However, your server-side controller actions are written in Apex, and as such are subject to all the usual Apex limits. A client-side controller handles events within a component. It’s a JavaScript resource that defines the functions for all of the component’s actions.
A client-side controller is a JavaScript object in object-literal notation containing a map of name-value pairs. Each name corresponds to a client-side action. Its value is the function code associated with the action. Client-side controllers are surrounded by parentheses and curly braces. Separate action handlers with commas (as you would with any JavaScript map). hope it will be helpful.

Please mark it as best answer if the information is informative.so that question is removed from an unanswered question and appear as a proper solution.

Thanks
Rahul Kumar
 
Best Answer chosen by Nikhil Bujade
AshishkAshishk
If you are using "/apex/vfpage" to open VF page in iframe, it is a change in context and origin as visualforce is loading from lightning.

There are mulitple redirects done before page is loaded if we use relative url, resulting in Performance issue in loading.

Try using absolute URL, please visit below article.

http://ashishsfdc.blogspot.com/2018/09/loading-visualforce-in-iframe.html (http://ashishsfdc.blogspot.com/2018/09/loading-visualforce-in-iframe.html" target="_blank)
MCooperMCooper 
On Opportuntities we have the default "Next Steps" field, but it's not very long and we'd like to retain back history of the progress of a deal.  I've created a long text field "Sales Progress".  Here's what I'd like to do using a workflow trigger and field update:  Whenever a new entry is made in Next Steps, copy that entry over to Sales Progress and add it to the bottom (or top) of the existing text.  What would the formula look like?
Best Answer chosen by MCooper
sfdc_ninjasfdc_ninja
You would want to create a workflow rule on the Opportunitiy object.

For evaluation criteria, you would want to use 'created, and every time it’s edited'.  

The Rule Criteria would be 

ISCHANGED(NextStep)

Then for an action, you would create a field update.  The update would be on the Sales_Progress__c field.  You would use a formual to set the new value.  The formula you would want to use would be 

Sales_Progress__c + BR() + BR() + $User.LastName + ', ' + $User.FirstName + ' ' + TEXT(Today()) + ' - ' + NextStep

This appends the the next step field to your custom sales progress field.  It also adds the user and the date so you know who made the change and when, so it should show a decent chronological story of the opportunity.  

Hope that helps