You need to sign in to do that
Don't have an account?
tengel
List of Available Records not Loading
I am modifying this awesome code package from Michael Farrington (http://www.michaelforce.org/recipeView?id=a0G30000006eVxVEAU) to build a VF page that will allow a user to add multiple competitors to an Opportunity at one time. It is SO CLOSE to working, but I have this one final hurdle to cross...
I am using a junction object to attach competitors to Opportunities. My list of options is stored in the Competitor_Option__c object, and then my Competitor__c object has a master-detail to Opportunity, and a lookup to Competitor_Option__c.
The VF page has two sections: Selected Competitors and Available Competitors. Everything is working great EXCEPT that my list of Available Competitors is not returning any results when the page is first loaded. If I hit backspace while in the page's search field, my Competitor_Options__c load. If I Remove a previously added option, the options load. Can anyone help me find what in my code is preventing any options from loading when the page first loads?
User-added image
VF page:
Apex extension:
I am using a junction object to attach competitors to Opportunities. My list of options is stored in the Competitor_Option__c object, and then my Competitor__c object has a master-detail to Opportunity, and a lookup to Competitor_Option__c.
The VF page has two sections: Selected Competitors and Available Competitors. Everything is working great EXCEPT that my list of Available Competitors is not returning any results when the page is first loaded. If I hit backspace while in the page's search field, my Competitor_Options__c load. If I Remove a previously added option, the options load. Can anyone help me find what in my code is preventing any options from loading when the page first loads?
User-added image
VF page:
<apex:page standardController="Opportunity" extensions="opportunityProductEntryExtension" > <apex:sectionHeader Title="Manage Competitors" subtitle="{!opportunity.Name}"/> <apex:messages style="color:red"/> <style> .search{ font-size:14pt; margin-right: 20px; } .fyi{ color:red; font-style:italic; } .label{ margin-right:10px; font-weight:bold; } </style> <script type='text/javascript'> // This script assists the search bar functionality // It will execute a search only after the user has stopped typing for more than 1 second // To raise the time between when the user stops typing and the search, edit the following variable: var waitTime = 0; var countDown = waitTime+1; var started = false; function resetTimer(){ countDown=waitTime+1; if(started==false){ started=true; runCountDown(); } } function runCountDown(){ countDown--; if(countDown<=0){ fetchResults(); started=false; } else{ window.setTimeout(runCountDown,1000); } } </script> <apex:form id="form"> <apex:outputPanel id="mainBody"> <!-- this is the upper table... a.k.a. the "Shopping Cart"--> <apex:pageBlock title="Selected Competitors" id="selected"> <apex:pageblockTable value="{!shoppingCart}" var="s"> <apex:column > <apex:commandLink value="Remove" action="{!removeFromShoppingCart}" reRender="selected,searchResults" immediate="true"> <!-- this param is how we send an argument to the controller, so it knows which row we clicked 'remove' on --> <apex:param value="{!s.Competitor__c}" assignTo="{!toUnselect}" name="toUnselect"/> </apex:commandLink> </apex:column> <apex:column headerValue="Competitor" value="{!s.Competitor__c}"/> <apex:column headerValue="Incumbent"> <apex:inputField value="{!s.Incumbent__c}" /> </apex:column> <apex:column headerValue="Winner"> <apex:inputField value="{!s.Winner__c}" /> </apex:column> <apex:column headerValue="Strengths"> <apex:inputField value="{!s.Strengths__c}" style="width:200px; height:100px" required="false"/> </apex:column> <apex:column headerValue="Weaknesses"> <apex:inputField value="{!s.Weaknesses__c}" style="width:200px; height:100px" required="false"/> </apex:column> <apex:column headerValue="Competing Producer"> <apex:inputField value="{!s.Producer__c}" required="false"/> </apex:column> </apex:pageblockTable> <apex:pageBlockButtons > <apex:commandButton action="{!onSave}" value="Save"/> <apex:commandButton action="{!onCancel}" value="Cancel" immediate="true"/> </apex:pageBlockButtons> </apex:pageBlock> <!-- this is the lower table: search bar and search results --> <apex:pageBlock id="block"> <apex:outputPanel styleClass="search"> Search for Competitors: </apex:outputPanel> <apex:actionRegion renderRegionOnly="false" immediate="true" id="region"> <apex:actionFunction name="fetchResults" action="{!updateAvailableList}" reRender="searchResults" status="searchStatus" id="function" /> <!-- here we invoke the scripting to get out fancy 'no button' search bar to work --> <apex:inputText value="{!searchString}" onkeydown="if(event.keyCode==13){this.blur();}else{resetTimer();}" style="width:300px" id="search" /> <i> <!-- actionStatus component makes it easy to let the user know when a search is underway --> <apex:actionStatus id="searchStatus" startText="searching..." stopText=" "/> </i> </apex:actionRegion> <br/> <br/> <apex:outputPanel id="searchResults"> <apex:pageBlockTable value="{!AvailableProducts}" var="a"> <apex:column width="100px;"> <!-- command button in a column... neato --> <apex:commandButton value="Select" action="{!addToShoppingCart}" reRender="selected,searchResults" immediate="true"> <!-- again we use apex:param to be able to tell the controller which row we are working with --> <apex:param value="{!a.Id}" assignTo="{!toSelect}" name="toSelect"/> </apex:commandButton> </apex:column> <apex:column headerValue="Competitor" value="{!a.Name}" width="300px;" /> <apex:column headerValue="Type" value="{!a.Competitor_Type__c}" /> </apex:pageBlockTable> <!-- We put up a warning if results exceed 100 rows --> <apex:outputPanel styleClass="fyi" rendered="{!overLimit}"> <br/> Your search returned over 100 results, use a more specific search string if you do not see the desired Competitor. <br/> </apex:outputPanel> </apex:outputPanel> </apex:pageBlock> </apex:outputPanel> </apex:form> </apex:page>
Apex extension:
public with sharing class opportunityProductEntryExtension { public Opportunity theOpp {get;set;} public String searchString {get;set;} public Competitor__c[] shoppingCart {get;set;} public Competitor_Option__c[] AvailableProducts {get;set;} public String toSelect {get; set;} public String toUnselect {get; set;} public Decimal Total {get;set;} public Boolean overLimit {get;set;} private Competitor__c[] forDeletion = new Competitor__c[]{}; public opportunityProductEntryExtension(ApexPages.StandardController controller) { theOpp = [select Id from Opportunity where Id = :controller.getRecord().Id limit 1]; // If products were previously selected need to put them in the "selected products" section to start with shoppingCart = [select Id, Name, Incumbent__c, Winner__c, Strengths__c, Weaknesses__c, Producer__c, Competitor__c from Competitor__c where Opportunity__c=:theOpp.Id order by Id Asc]; } public void updateAvailableList() { // We dynamically build a query string and exclude items already in the shopping cart String qString = 'select Id, Name, Competitor_Type__c from Competitor_Option__c where Active__c=true'; // note that we are looking for the search string entered by the user in the name OR description // modify this to search other fields if desired if(searchString!=null){ qString+= ' and (Name like \'%' + searchString + '%\')'; } Set<Id> selectedEntries = new Set<Id>(); for(Competitor__c d:shoppingCart){ selectedEntries.add(d.Competitor__c); } if(selectedEntries.size()>0){ String tempFilter = ' and Id not in ('; for(Id i : selectedEntries){ tempFilter+= '\'' + (String)i + '\','; } String extraFilter = tempFilter.substring(0,tempFilter.length()-1); extraFilter+= ')'; qString+= extraFilter; } qString+= ' order by Name'; qString+= ' limit 101'; system.debug('qString:' +qString); AvailableProducts = database.query(qString); // We only display up to 100 results... if there are more than we let the user know (see vf page) if(AvailableProducts.size()==101){ AvailableProducts.remove(100); overLimit = true; } else{ overLimit=false; } } public void addToShoppingCart(){ // This function runs when a user hits "select" button next to a product for(Competitor_Option__c d : AvailableProducts){ if((String)d.Id==toSelect){ shoppingCart.add(new Competitor__c(Opportunity__c=theOpp.Id, Competitor__c=d.Id)); break; } } updateAvailableList(); } public PageReference removeFromShoppingCart(){ // This function runs when a user hits "remove" on an item in the "Selected Products" section Integer count = 0; for(Competitor__c d : shoppingCart){ if((String)d.Competitor__c==toUnselect){ if(d.Competitor__c!=null) forDeletion.add(d); shoppingCart.remove(count); break; } count++; } updateAvailableList(); return null; } public PageReference onSave(){ // If previously selected products are now removed, we need to delete them if(forDeletion.size()>0) delete(forDeletion); // Previously selected products may have new quantities and amounts, and we may have new products listed, so we use upsert here try{ if(shoppingCart.size()>0) upsert(shoppingCart); } catch(Exception e){ ApexPages.addMessages(e); return null; } // After save return the user to the Opportunity return new PageReference('/' + ApexPages.currentPage().getParameters().get('Id')); } public PageReference onCancel(){ // If user hits cancel we commit no changes and return them to the Opportunity return new PageReference('/' + ApexPages.currentPage().getParameters().get('Id')); } }
tengel
Image of page, for further clarification: