0

I have a visualforce page where I have a form with 4 separate selectLists with options populated based on different user groups. So far so good. This form also has a submit button which triggers a custom action which is supposed to insert a record with fields populated by the selected options. The problem I am having is that when the user picks one or more options and then hits submit, the action doesn't trigger at all. However, when no option is selected, the action does trigger (though it doesn't insert because its null).

My question is why does selecting an option make the commandButton fail to trigger the action?

Code below:

Visualforce Page

<apex:page standardController="Opportunity" extensions="OpportunityApprovalControllerExt" title="Submit Opportunity for Approval" >
    <style type="text/css">
        .sbox { width: 200px; }
    </style>

    <apex:form >
        <apex:pageBlock >
            <apex:pageBlockSection title="Opportunity Details">
                <apex:outputField value="{!Opportunity.Name}" label="Name: "/>
                <apex:outputField value="{!Opportunity.ExpectedRevenue}" label="Revenue: "/>
                <apex:outputField value="{!Opportunity.AccountId}" label="Related Account: "/>
                <apex:outputField value="{!Opportunity.StageName}" label="Stage: "/>
            </apex:pageBlockSection>
            <apex:pageBlockSection title="Applicable Approver Levels">
                <apex:actionRegion >
                       <apex:outputLabel value="Approver 2: " for="app2"/>
                    <apex:selectList styleClass="sbox" value="{!selectedApprover2}" id="app2" size="1" label="Approver 2:"
                                     disabled="{!IF(Opportunity.ExpectedRevenue != null && Opportunity.ExpectedRevenue > 200000, 'false', 'true')}">
                        <apex:selectOptions id="options2" value="{!Level2}"/> 
                    </apex:selectList>
                </apex:actionRegion>
                <apex:actionRegion >
                    <apex:outputLabel value="Approver 3: " for="app3"/>
                    <apex:selectList styleClass="sbox" value="{!selectedApprover3}" id="app3" size="1" label="Approver 3:"
                                     disabled="{!IF(Opportunity.ExpectedRevenue != null && Opportunity.ExpectedRevenue > 300000, 'false', 'true')}">
                        <apex:selectOptions id="options3" value="{!Level3}"/> 
                    </apex:selectList>
                </apex:actionRegion>
                <apex:actionRegion >
                       <apex:outputLabel value="Approver 4: " for="app4"/>
                    <apex:selectList styleClass="sbox" value="{!selectedApprover4}" id="app4" size="1" label="Approver 4:"
                                     disabled="{!IF(Opportunity.ExpectedRevenue != null && Opportunity.ExpectedRevenue > 400000, 'false', 'true')}">
                        <apex:selectOptions id="options4" value="{!Level4}"/> 
                    </apex:selectList>
                </apex:actionRegion>
                <apex:actionRegion >
                       <apex:outputLabel value="Approver 5: " for="app5"/>
                    <apex:selectList styleClass="sbox" value="{!selectedApprover5}" id="app5" size="1" label="Approver 5:"
                                     disabled="{!IF(Opportunity.ExpectedRevenue != null && Opportunity.ExpectedRevenue > 500000, 'false', 'true')}">
                        <apex:selectOptions id="options5" value="{!Level5}"/> 
                    </apex:selectList>
                </apex:actionRegion>

            </apex:pageBlockSection>
            <apex:commandButton action="{!newOppApproval}" title="Submit" id="approvalID" value="Submit" />
            <apex:commandButton action="{!cancel}" value="Cancel"/>
        </apex:pageBlock>
    </apex:form>

</apex:page>

Apex Controller

/*  11/26/19
 *  Infosys Ltd. Post Training Project 1: Opportunity Approval Process
 *  Controller Extension for Opportunity Visualforce page
 */
public class OpportunityApprovalControllerExt {
    public final Opportunity opp;
    public static Opportunity_Approval__c oppApproval {get;set;}
    public static List<SelectOption> Level2Options, Level3Options, Level4Options, Level5Options;
    public String selectedApprover2 {get;set;}
    public String selectedApprover3 {get;set;}
    public String selectedApprover4 {get;set;}
    public String selectedApprover5 {get;set;}

    public OpportunityApprovalControllerExt(ApexPages.StandardController stdController){
        System.debug('\nCONSTRUCTOR DOES STUFF');
        this.opp = (Opportunity)stdController.getRecord();
        oppApproval = new Opportunity_Approval__c();
        oppApproval.Opportunity__c = opp.id;
        Level2Options = getApproverOptions(2);
        Level3Options = getApproverOptions(3);
        Level4Options = getApproverOptions(4);
        Level5Options = getApproverOptions(5);
    }

    public void newOppApproval(){
      oppApproval.Approver_2__c = selectedApprover2;
      oppApproval.Approver_3__c = selectedApprover3;
      oppApproval.Approver_4__c = selectedApprover4;
      oppApproval.Approver_5__c = selectedApprover5;
      System.debug('\n New Opp Approval');
      System.debug('\n selectedApprover2 :: Expected =' + selectedApprover2 + ' : Actual = oppApproval.Approver_2__c');
      try{
            System.debug('\nINSERTING NEW OPP APP ');
            insert oppApproval;
        }catch(DmlException ex){
            System.debug('\n\n INSERTION Exception ='+ex.getMessage()+'\n\n');
        }catch(NullPointerException nex){
            System.debug('\nNULL POINTER EXCEPTION: no opp to insert');
        }catch(Exception exc){
            System.debug('\nEXCEPTION = '+exc.getMessage());
        }
    }

    public static List<selectOption> getLevel2(){
        return Level2Options;
    }

    public static List<selectOption> getLevel3(){
        return Level3Options;
    }

    public static List<selectOption> getLevel4(){
        return Level4Options;
    }

    public static List<selectOption> getLevel5(){
        return Level5Options;
    }

    public static List<selectOption> getApproverOptions(Integer approverLevel){
        List<selectOption> options = new List<selectOption>();
        options.add(new SelectOption('', '-None-'));
        Id groupId = getGroupId(approverLevel);
        if(groupId != null){
            Set<id> userids = getUsersFromGroupIds(groupId);
            for(User user : [SELECT Name, Id FROM User WHERE Id IN :userIds]){
                options.add(new SelectOption(user.id, user.Name));
            }
        }
        return options;
    }

    private static Id getGroupId(Integer approverLevel){
        String nameLike = '%' + approverLevel + '%';
        System.debug('Approver level--> '+ approverLevel);
        //nameLike = '%test%'; //for testing obviously
        List<Group> grp = [SELECT Name, id FROM Group WHERE Name LIKE :nameLike];
        //System.assertEquals(1, grp.size(), 'Expected only one group returned');
        if(grp.size() == 1){
            return grp[0].id;
        }else{
            return null;
        }
    }

    public static Set<Id> getUsersFromGroupIds(Set<Id> groupIds) {
        String userType = Schema.SObjectType.User.getKeyPrefix();
        String groupType = Schema.SObjectType.Group.getKeyPrefix();
        Set<Id> userIds = new Set<Id>();
        Set<Id> innerGroupIds = new Set<Id>();
        for (GroupMember m : [Select UserOrGroupId From GroupMember Where GroupId In :groupIds]) {
            if (((String)m.UserOrGroupId).startsWith(userType))
                userIds.add(m.UserOrGroupId);
            else
                innerGroupIds.add(m.UserOrGroupId);
        }
        if (innerGroupIds.size() > 0)
            userIds.addAll(getUsersFromGroupIds(innerGroupIds));
        return userIds;
    }

    // A helper if you just want users from one group.
    public static Set<Id> getUsersFromGroupIds(Id groupId) {
        return getUsersFromGroupIds(new Set<Id>{groupId});
    }

}
  • Is there any reason you've placed an actionRegion around each selectlist? – Nick Cook Dec 10 '19 at 23:59
  • @NickCook No real reason to be honest, but modifying that did not affect the issue at hand. – Jeremy Canning Dec 11 '19 at 22:21
0

So I ended up solving this problem myself by making some changes to the controller. In essence by problem was trying to store the results of several getApproverOptions(#) calls in static SelectOption list variables instead of just running the call in the get merge field dynamically. The changes I needed to make are below:

public class OpportunityApprovalControllerExt {
    public final Opportunity opp;
    public static Opportunity_Approval__c oppApproval {get;set;}
    //removed SelectOption lists altogether
    public String selectedApprover2 {get;set;}
    public String selectedApprover3 {get;set;}
    public String selectedApprover4 {get;set;}
    public String selectedApprover5 {get;set;}

public OpportunityApprovalControllerExt(ApexPages.StandardController stdController){
        System.debug('\nCONSTRUCTOR DOES STUFF');
        this.opp = (Opportunity)stdController.getRecord();
        oppApproval = new Opportunity_Approval__c();
        oppApproval.Opportunity__c = opp.id;
        //removed instantiation of SelectOption lists
    }

...

    //no longer returning the selectOption list variables and instead just running the method
    public static List<selectOption> getLevel2(){
        return getApproverOptions(2);
    }

    public static List<selectOption> getLevel3(){
        return getApproverOptions(3);
    }

    public static List<selectOption> getLevel4(){
        return getApproverOptions(4);
    }

    public static List<selectOption> getLevel5(){
        return getApproverOptions(5);
    }

//rest of code

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.