2

If the checkboxes are re-rendered, you can see that your input has been ignored. Whether re-rendered or not, the controller is unaware of your input upon form submission (it throws the exception that I planted there in case no selections were made). Note that the checkbox located OUTSIDE the repeat (id="bogus") functions properly.

This implementation of checkboxes in a repeat is certainly nothing novel, and I've done similar things hundreds of times in the past, so what is going wrong here?

Here is the page markup

<apex:form id="theForm">
    <apex:pageMessages id="errors" />
    <c:LockScreen />
    <apex:pageBlock id="theBlock" title="Select Email Recipients">
        <apex:pageBlockButtons id="pageButtons" location="both" >
            <apex:commandButton value="Add Recipients" action="{!generate}" status="lockScreen" reRender="theForm"  />
            <apex:commandButton value="Cancel" immediate="true" action="{!cancel}" />
        </apex:pageBlockButtons>


        <apex:inputCheckbox id="bogus" value="{!targets['Team__c'][0].selected}" ><apex:actionSupport event="onchange" reRender="theBlock" status="lockScreen" /></apex:inputCheckbox>
        <apex:repeat id="objects" value="{!targets}" var="obj">

            <apex:variable value="{!targets[obj]}" var="rows" />
            <apex:pageBlock id="section"  title="{!$ObjectType[obj].LabelPlural}" >
                <apex:outputText rendered="{!rows.empty}" value="No related {!$ObjectType[obj].LabelPlural}" />
                <apex:pageBlockTable id="mainTable" value="{!targets[obj]}" var="row" rendered="{!!rows.empty}" >
                    <apex:column id="selectionCol" headerValue="Select" width="60px" >
                        <apex:inputCheckbox id="selectBox" value="{!row.selected}" >
                            <apex:actionSupport id="update" event="onchange" status="lockScreen" reRender="theBlock" />
                        </apex:inputCheckbox>
                    </apex:column>
                    <apex:column headerValue="{!$ObjectType[obj].fields.Name.Label}" value="{!row.record['Name']}" />
                </apex:pageBlockTable>
            </apex:pageBlock>
        </apex:repeat>

    </apex:pageBlock>
</apex:form>

and here's the controller, though it isn't doing anything novel

public with sharing class SelectIncidentEmailRecipientsCtrl {

    public Incident_Email__c record                   {get; set;}
    public Map<String,ObjectWrap[]> targets           {get; set;}
    public Boolean check                              {get; set;}
    private Map<Id,Plan__c> plans                     {get; set;}
    private ApexPages.StandardController stdCon;

    public SelectIncidentEmailRecipientsCtrl(ApexPages.StandardController stdCon){
        this.stdCon = stdCon;
        targets = new Map<String,List<ObjectWrap>>{'Team__c'=>new List<ObjectWrap>(), 'Roster__c'=>new List<ObjectWrap>(),
                                                   'User'=>new List<ObjectWrap>(), 'Key_Contact__c'=>new List<ObjectWrap>()};
        if(!Test.isRunningTest()){
            stdCon.addFields(new String[]{'Incident__c','Body__c','Subject__c'});
        }
        this.record = (Incident_Email__c)stdCon.getRecord();
        this.plans = new Map<Id,Plan__c>([SELECT Id, Name FROM Plan__c WHERE Id IN (SELECT Plan__c FROM Incident_Plan__c WHERE Incident__c =:record.Incident__c)]);
        Set<Id> planIDs = plans.keySet();
        targets.get('Roster__c').addAll( wrapObjects([SELECT Id, Name FROM Roster__c WHERE Id IN (SELECT Roster__c FROM Plan_Roster__c WHERE Plan__c IN :planIDs) ORDER BY Name] ));
        targets.get('Team__c'  ).addAll( wrapObjects([SELECT Id, Name FROM Team__c WHERE Id IN (SELECT Team__c FROM Plan_Team__c WHERE Plan__c IN :planIDs) ORDER BY Name] ));

    }


    public PageReference generate(){
        Incident_Email_Recipient__c[] recipients = new List<Incident_Email_Recipient__c>();
        for(ObjectWrap[] wraps : targets.values()){
            sObject[] selected = new List<sObject>();
            for(ObjectWrap wrap : wraps){
                if(wrap.selected){
                    selected.add(wrap.record);
                }
            }
            if(!selected.isEmpty())
                recipients.addAll(IncidentManagementUtil.getRecipients(record, selected));
        }

        try{
            if(recipients.isEmpty())
                throw new FFException('No records selected');
            insert recipients;
            return stdCon.cancel();
        }catch(Exception e){
            ApexPages.addMessages(e);
            return null;
        }
    }

    private ObjectWrap[] wrapObjects(sObject[] objects){
        ObjectWrap[] wraps = new List<ObjectWrap>();
        for(sObject obj : objects)
            wraps.add(new ObjectWrap(obj));
        return wraps;
    }

    public class ObjectWrap{
        public Boolean selected         {get; set;}
        public sObject record           {get; set;}

        public ObjectWrap(sObject obj){
            this.record = obj;
            this.selected = false;
        }

    }

}

Thinking that it might be a issue, I even tried decrementing the API versions, but to no avail. I've opened a ticket with support in case this is a legit platform bug in Summer '15, but I'm hoping our community might be able to come to my rescue

4
  • Are any of the contacts above in your rosters that you have lookups to their email accounts, etc, lookups to Users? If so, is the OWD on the User Object set to Private? Sharing behavior for this changed in SU 15 is why I ask. Sharing on User object is now respected when set to private where it was previously ignored. – crmprogdev Jun 19 '15 at 16:39
  • No, but I actually haven't even written the portions to retrieve contacts or users yet. Right now, it's only dealing with the Teams and Rosters – RenegadeCoder Jun 19 '15 at 16:49
  • Perhaps it's because you put your <apex:actionSupport id="update" event="onchange" status="lockScreen" reRender="theBlock" /> or duplicated it inside the block instead of outside it where you located <apex:inputCheckbox value= – crmprogdev Jun 19 '15 at 16:55
  • I actually just have the actionSupports in there to more quickly see the issue; behavior is the same even if I remove all actionSupports and re-renders – RenegadeCoder Jun 19 '15 at 18:30

Your Answer

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

Browse other questions tagged or ask your own question.