1

I have a visualforce page that we want to use to look up campaign members. The user is supposed to select a campaign, and then get an input field to type in member numbers. Those member numbers are then searched for in the campaignmember object. If found, that status needs to be displayed, and then the user can type in another one.

For some reason that I can't figure out is that the variables allowScan and scanStatus never get the value assigned in checkScanValue() that I would expect. I know the function is called, because I can see the DEBUG message in the logs.

VisualForce page:

 <apex:page docType="html-5.0" controller="ElectionCampaign_Scan" showHeader="false">

    <apex:form id="TopPageBlock">
        <apex:pageBlock >
            <apex:pageBlockSection id="CampaignSelection" columns="2">
                <apex:outputLabel value="Campaign" />
                <apex:selectList size="1" value="{!campaignSelectedId}">
                    <apex:selectOptions value="{!campaignOptions}"/>
                    <apex:actionSupport event="onchange" action="{!checkCampaignValue}" />
                </apex:selectList>
            </apex:pageBlockSection> 
            <apex:pageBlockSection id="CampaignInfo" columns="1">
                <apex:outputField value="{!campaignSelected.Name}"/>
                <apex:outputField value="{!campaignSelected.Type}"/>
                <apex:outputField value="{!campaignSelected.Primary_Theme__c}"/>
                <apex:outputField value="{!campaignSelected.Secondary_Theme__c}"/>
                <apex:outputLabel value="{!campaignMemberValue}" />
                <apex:outputLabel value="{!scanStatus}" />
                <apex:outputLabel value="{!allowScan}" />
            </apex:pageBlockSection>
        </apex:pageBlock>

        <apex:pageBlock rendered="{!campaignSelected.Name <> ''}" id="CampaignMemberScan">
            <apex:pageBlockSection id="CampaignMemberScanValue" columns="1">
                <apex:outputLabel value="Member ID:" />
                <apex:input type="text" value="{!campaignMemberValue}" rendered="{!allowScan}" >
                    <apex:actionSupport event="onchange" action="{!checkScanValue}" reRender="CampaignMemberScanStatus"/>
                </apex:input>
            </apex:pageBlockSection>
            <apex:pageBlockSection id="CampaignMemberScanStatus" columns="1">
                <apex:outputText rendered="{! !allowScan}" id="timeout">
                    <p>
                        This should show sometime!
                    </p>
                    <script>
                    //setTimeout(CallApexClear(), 10000);
                    </script>
                </apex:outputText>
                <apex:outputText value="{0}: {1} {2}" rendered="{!if(allowScan==true,true,true)}" >
                    <apex:param value="{!campaignMemberId}" />
                    <apex:param value="{!campaignMemberName}" />
                    <apex:param value="{!campaignMemberStatus}" />
                </apex:outputText>
            </apex:pageBlockSection> 
            <apex:messages />
        </apex:pageBlock>

    </apex:form>

</apex:page>

Controller:

public class ElectionCampaign_Scan 
{
    public Id campaignSelectedId { get;set; }
    public Campaign campaignSelected { get;set; }
    public List<SelectOption> campaignOptions { get;set; }

    public string campaignMemberValue { get;set; }
    public string campaignMemberName { get;set; }
    public string campaignMemberID { get;set; }
    public string campaignMemberStatus { get;set; }
    public string scanStatus { get;set; }

    public boolean allowScan { get; set; }

    public boolean isSandbox { get; set; }

    public ElectionCampaign_Scan() 
    {
        System.debug('ElectionCampaign_Scan');

        isSandbox = [SELECT Id, IsSandbox FROM Organization LIMIT 1].IsSandbox;

        List<Campaign> Campaigns = [SELECT Id, Name from Campaign WHERE Primary_Theme__c LIKE '%Election%' AND IsActive = True];

        CampaignOptions = new list<SelectOption>();
        CampaignOptions.add(new SelectOption('',''));
        for (Campaign c : Campaigns)
        {
            CampaignOptions.add(new SelectOption(c.id,c.Name));
        }

        allowScan = true;
    }


    public void checkCampaignValue()
    {
        System.debug('checkCampaignValue');

        List<Campaign> campaigns = [SELECT Id, Name, Type, SubType__c, Category__c, Primary_Theme__c, Secondary_Theme__c, Status, StartDate, EndDate FROM Campaign WHERE Id = :campaignSelectedId LIMIT 1];
        if( campaigns.isEmpty() == false )
        {
            campaignSelected = campaigns[0];
        }

    }

    public void checkScanValue()
    {
        scanStatus = '';
        allowScan = false;

        System.debug('checkScanValue');
        List<CampaignMember> campaignMembers = [SELECT Id, Name, Status FROM CampaignMember WHERE Contact.Unionware_Calculated_Identifier__c = :campaignMemberValue AND CampaignId = :campaignSelected.Id LIMIT 1];
        if( campaignMembers.isEmpty() == true )
        {
            campaignMemberID = campaignMemberValue;
            campaignMemberName = '';
            campaignMemberStatus = 'Not part of the campaign';

            scanStatus = 'Not part of the campaign';
        }
        else
        {
            campaignMemberID = campaignMemberValue;
            campaignMemberName = campaignMembers[0].Name;
            campaignMemberStatus = campaignMembers[0].status;
            if( campaignMembers[0].status == 'Send' )
            {
                scanStatus = 'Send';
            }
            else
            {
                 scanStatus = 'Already scanned';
            }
        }
    }

}

Thanks!

  • 2
    Can you say more specifically what you're seeing happen/not happen in your page? Why do you say that those variables are not getting the correct val;ue assigned? What value should they be assigned and what would that do on the page? – Thomas Taylor May 3 '18 at 0:48
  • After entering checkScanValue(), allowScan should be false and never turn true again. But I'm not seeing this. I had some Rendered="{!allowScan}" in the VF code, but those parts never disappeared. – Wouter van Wageningen May 3 '18 at 5:08
  • After removing a lot of code and making things a lot simpler, I found that using apex:actionsupport (onchange) with apex:input does not generate what you would expect it to do. Instead of calling the controller method every time, it only does it on the first change of the value. After removing the actionsupport and adding a onchange to the apex:input, I'm seeing better behaviour. I'll need to do more testing, bit for now, this seems to be the way forward. – Wouter van Wageningen May 3 '18 at 5:12
2

A few thoughts:

  1. On the apex:actionSupport reRender add "CampaignInfo". That way you should see the new values rendered back in that pageBlockSection, which is the only location scanStatus appears.
  2. rendered="{!if(allowScan==true,true,true)}" This looks suspect. One of those should be a false at the very least. You might also try rendered="{! (allowScan==true)}" and skip the if statement that returns true/false.
  • 1) Oops, I forgot that. 2) That used to have other logic in it, and I just left the if() in place to remind me to put the logic back after I figured out what the issues were. – Wouter van Wageningen May 3 '18 at 5:04
0

This turned out to be a lot weirder than I expected. The onchange attribute of an apex:input element only fires on the first change of the value. After that, nothing happens in the controller method.

So instead I decided to see if I could fix it with regular HTML and some JavaScript around it. That seemed to work. It required me to pass the value of the <input> tag through JavaScript and <apex:actionFunction> and <apex:param> back to the controller. I also had to add a dummy <input> field to allow the focus to pass to another field. Luckily, this field can have the visibility:hidden style and it still works.

Here is the completed test case:

Controller:

public class scantest  
{
    public Campaign campaignSelected { get;set; }

    public string campaignMemberValue { get;set; }
    public string campaignMemberName { get;set; }
    public string campaignMemberID { get;set; }
    public string campaignMemberStatus { get;set; }
    public string scanStatus { get;set; }
    public string dummy { get;set; }

    public boolean allowScan { get; set; }

    public boolean isSandbox { get; set; }

    public scantest() 
    {
        System.debug('ElectionCampaign_Scan');

        isSandbox = [SELECT Id, IsSandbox FROM Organization LIMIT 1].IsSandbox;

        List<Campaign> Campaigns = [SELECT Id, Name from Campaign WHERE Primary_Theme__c LIKE '%Election%' AND IsActive = True];
        campaignSelected = Campaigns[0];

        allowScan = true;
    }


    public void checkScanValue()
    {
        scanStatus = '';
        allowScan = false;

        System.debug('checkScanValue');
        System.debug(campaignMemberValue);

        List<CampaignMember> campaignMembers = [SELECT Id, Name, Status FROM CampaignMember WHERE Contact.Unionware_Calculated_Identifier__c = :campaignMemberValue AND CampaignId = :campaignSelected.Id LIMIT 1];
        if( campaignMembers.isEmpty() == true )
        {
            campaignMemberID = campaignMemberValue;
            campaignMemberName = '';
            campaignMemberStatus = 'Not part of the campaign';

            scanStatus = 'Not part of the campaign';
        }
        else
        {
            campaignMemberID = campaignMemberValue;
            campaignMemberName = campaignMembers[0].Name;
            campaignMemberStatus = campaignMembers[0].status;
            if( campaignMembers[0].status == 'Send' )
            {
                scanStatus = 'Send';
            }
            else
            {
                scanStatus = 'Already scanned';
            }
        }
    }
}

VF:

<apex:page docType="html-5.0" controller="scantest" showHeader="false">

    <apex:form id="TopPageBlock">
        <apex:actionFunction name="passValue" action="{!checkScanValue}" reRender="CampaignMemberScanStatus" status="myStatus">
        <apex:param name="firstParam" assignTo="{!campaignMemberValue}" value="" />
        </apex:actionFunction>

        <apex:pageBlock id="CampaignMemberScan">
            <apex:pageBlockSection id="CampaignMemberScanValue" columns="1">
                <apex:outputLabel value="Member ID:" />
                <input name="MemberID" type="Number" maxlength="8" onchange="CheckMemberID(this.value)" autocomplete="off" />
                <input name="dummy" type="text" style="visibility: hidden" />
            </apex:pageBlockSection>

            <apex:pageBlockSection id="CampaignMemberScanStatus" columns="1">
                <apex:outputText value="{0}: {1} {2}" rendered="{!if(allowScan==true,true,true)}" >
                    <apex:param value="{!campaignMemberId}" />
                    <apex:param value="{!campaignMemberName}" />
                    <apex:param value="{!campaignMemberStatus}" />
                </apex:outputText>
                <apex:outputText value="{!scanStatus}"></apex:outputText>
            </apex:pageBlockSection> 

        </apex:pageBlock>

    </apex:form>
    <script type="text/javascript">
        function CheckMemberID( MemberID )
        {
            //alert( MemberID );
            passValue( MemberID );
        }
    </script>

</apex:page>

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.