function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
CharlieLangCharlieLang 

Dynamic Search

I have used the dynamic search code from Jeff Douglas http://blog.jeffdouglas.com/2010/07/13/building-a-dynamic-search-page-in-visualforce/

 

i have run into some difficulties - the dynamic search is not working and i can not work it out so i added a submit button but this just gives an error

Attempt to de-reference a null object 

 

this is the controller

public with sharing class ContactSearchController {

    

  // the soql without the order and limit
  private String soql {get;set;}
  // the collection of contacts to display
  public List <Contact> contacts {get;set;}

  // the current sort direction. defaults to asc
  public String sortDir {
    get  { if (sortDir == null) {  sortDir = 'asc'; } return sortDir;  }
    set;
  }

  // the current field to sort by. defaults to last name
  public String sortField {
    get  { if (sortField == null) {sortField = 'lastName'; } return sortField;  }
    set;
  }

  // format the soql for display on the visualforce page
  public String debugSoql {
    get { return soql + ' order by ' + sortField + ' ' + sortDir + ' limit 20'; }
    set;
  }

  // init the controller and display some sample data when the page loads
  public ContactSearchController() {
    soql = 'select firstName, lastName, account.name, Employee_Number__c from contact where account.name != null';
    runQuery();
  }

  // toggles the sorting of query from asc<-->desc
  public void toggleSort() {
    // simply toggle the direction
    sortDir = sortDir.equals('asc') ? 'desc' : 'asc';
    // run the query again
    runQuery();
  }

  // runs the actual query
  public void runQuery() {

    try {
      contacts = Database.query(soql + ' order by ' + sortField + ' ' + sortDir + ' limit 20');
    } catch (Exception e) {
      ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Ooops!'));
    }

  }

  // runs the search with parameters passed via Javascript
  public PageReference runSearch() {

    String firstName = Apexpages.currentPage().getParameters().get('firstName');
    String lastName = Apexpages.currentPage().getParameters().get('lastName');
    String accountName = Apexpages.currentPage().getParameters().get('accountName');
    
    soql = 'select firstName, lastName, account.name, Employee_Number__c, from contact where account.name != null';
    if (!firstName.equals(''))
      soql += ' and firstName LIKE \''+String.escapeSingleQuotes(firstName)+'%\'';
    if (!lastName.equals(''))
      soql += ' and lastName LIKE \''+String.escapeSingleQuotes(lastName)+'%\'';
    if (!accountName.equals(''))
      soql += ' and account.name LIKE \''+String.escapeSingleQuotes(accountName)+'%\'';
    

    // run the query again
    runQuery();

    return null;
  }

  

}

 and this is the VF Page

 

If anyone can help me you would be a lifesaver!!!

<apex:page controller="ContactSearchController" sidebar="false">

  <apex:form >
  <apex:pageMessages id="errors" />

  <apex:pageBlock title="Find Me A Customer!" mode="edit">
<table width="100%" border="0">
<tr>
<td width="200" valign="top">

      <apex:pageBlock title="Parameters" mode="edit" id="criteria">

      <script type="text/javascript">
      function doSearch() {
        searchServer(
          document.getElementById("firstName").value,
          document.getElementById("lastName").value,
          document.getElementById("accountName").value,
                    );
      }
      </script> 

      <apex:actionFunction name="searchServer" action="{!runSearch}" >
          <apex:param name="firstName" value="" />
          <apex:param name="lastName" value="" />
          <apex:param name="accountName" value="" />
       
      </apex:actionFunction>
<table cellpadding="2" cellspacing="2">
<tr>
<td style="font-weight:bold;">First Name<br/>
<input type="text" id="firstName" onkeyup="doSearch();"/>
        </td>
</tr>
<tr>
<td style="font-weight:bold;">Last Name<br/>
<input type="text" id="lastName" onkeyup="doSearch();"/>
        </td>
</tr>
<tr>
<td style="font-weight:bold;">Account<br/>
<input type="text" id="accountName" onkeyup="doSearch();"/>
        </td>
      <tr>
        <td>
<apex:commandButton value="Search" action="{!runSearch}" rerender="results,debug,errors"/>
</td>
</tr>
</tr>
<tr>

</tr>
</table>

      </apex:pageBlock>
</td>
<td valign="top">

    <apex:pageBlock mode="edit" id="results">

        <apex:pageBlockTable value="{!contacts}" var="contact">

<apex:column >
                <apex:facet name="header">
                    <apex:commandLink value="Employee ID" action="{!toggleSort}" rerender="results,debug">
                        <apex:param name="sortField" value="Employee_Number__c" assignTo="{!sortField}"/>
                    </apex:commandLink>
                </apex:facet>
                <apex:outputField value="{!contact.Employee_Number__c}"/>
            </apex:column>


            <apex:column >
                <apex:facet name="header">
                    <apex:commandLink value="First Name" action="{!toggleSort}" rerender="results,debug">
                        <apex:param name="sortField" value="firstName" assignTo="{!sortField}"/>
                    </apex:commandLink>
                </apex:facet>
                <apex:outputField value="{!contact.firstName}"/>
            </apex:column>

            <apex:column >
                <apex:facet name="header">
                    <apex:commandLink value="Last Name" action="{!toggleSort}" rerender="results,debug">
                        <apex:param name="sortField" value="lastName" assignTo="{!sortField}"/>
                    </apex:commandLink>
                </apex:facet>
                <apex:outputField value="{!contact.lastName}"/>
            </apex:column>

            <apex:column >
                <apex:facet name="header">
                    <apex:commandLink value="Account" action="{!toggleSort}" rerender="results,debug">
                        <apex:param name="sortField" value="account.name" assignTo="{!sortField}"/>
                    </apex:commandLink>
                </apex:facet>
                <apex:outputField value="{!contact.account.name}"/>
            </apex:column>


            

        </apex:pageBlockTable>

    </apex:pageBlock>
</td>
</tr>
</table>

  <apex:pageBlock title="Debug - SOQL" id="debug">
      <apex:outputText value="{!debugSoql}" />
  </apex:pageBlock>    

  </apex:pageBlock>

  </apex:form>

</apex:page>
Best Answer chosen by Admin (Salesforce Developers) 
bob_buzzardbob_buzzard

I've got this working in my dev org.  Issues were:

 

1. In the doSearch method, you had a bonus comma after the final parameter:

 

 function doSearch() {
        searchServer(
          document.getElementById("firstName").value,
          document.getElementById("lastName").value,
          document.getElementById("accountName").value,  <-- bonus comma
                    );

 2. The searchServer actionfunction must rerender something for the parameters to be sent back, otherwise its just a page refresh.

 

 <apex:actionFunction name="searchServer" action="{!runSearch}" rerender="results">

 

 

3.  Null protected the first/last/account name parameters in the runSearch method:

 

    if ( (null!=firstName) && (!''.equals(firstName)) )
      soql += ' and firstName LIKE \''+String.escapeSingleQuotes(firstName)+'%\'';
    if ( (null!=lastName) && (!''.equals(lastName)) )
      soql += ' and lastName LIKE \''+String.escapeSingleQuotes(lastName)+'%\'';
    if ( (null!=accountname) && (!''.equals(accountName)) )
      soql += ' and account.name LIKE \''+String.escapeSingleQuotes(accountName)+'%\'';

 

All Answers

bob_buzzardbob_buzzard

I think the null pointer exception is coming from this section of code:

 

if (!firstName.equals(''))
      soql += ' and firstName LIKE \''+String.escapeSingleQuotes(firstName)+'%\'';
    if (!lastName.equals(''))
      soql += ' and lastName LIKE \''+String.escapeSingleQuotes(lastName)+'%\'';
    if (!accountName.equals(''))

 You aren't passing parameters from the submit button, so firstName, lastName and accountName will be null.  If you then attempt to execute the equals method on these variables you are dereferencing a null pointer and hence the exception

CharlieLangCharlieLang

Thanks Bob. 

 

Any idea on how i might be able to fix it as i've really got no idea. thanks for your contined help!!

bob_buzzardbob_buzzard

There's also a bonus comma in your query:

 

 soql = 'select firstName, lastName, account.name, Employee_Number__c, from contact

 the comma after Employee_Number__c will cause the dynamic soql to fail.

CharlieLangCharlieLang

That hasnt fixed it

 

Seems odd that the onkeyup part isnt working, thats the bit i can't get my head round....

bob_buzzardbob_buzzard

I've got this working in my dev org.  Issues were:

 

1. In the doSearch method, you had a bonus comma after the final parameter:

 

 function doSearch() {
        searchServer(
          document.getElementById("firstName").value,
          document.getElementById("lastName").value,
          document.getElementById("accountName").value,  <-- bonus comma
                    );

 2. The searchServer actionfunction must rerender something for the parameters to be sent back, otherwise its just a page refresh.

 

 <apex:actionFunction name="searchServer" action="{!runSearch}" rerender="results">

 

 

3.  Null protected the first/last/account name parameters in the runSearch method:

 

    if ( (null!=firstName) && (!''.equals(firstName)) )
      soql += ' and firstName LIKE \''+String.escapeSingleQuotes(firstName)+'%\'';
    if ( (null!=lastName) && (!''.equals(lastName)) )
      soql += ' and lastName LIKE \''+String.escapeSingleQuotes(lastName)+'%\'';
    if ( (null!=accountname) && (!''.equals(accountName)) )
      soql += ' and account.name LIKE \''+String.escapeSingleQuotes(accountName)+'%\'';

 

This was selected as the best answer
CharlieLangCharlieLang

Bob. thats amazing. thatnkyou so much for your help.

 

One more question ;-)

 

any idea on how i can make each of the lines in the search results a link to the relavant page?

bob_buzzardbob_buzzard

I usually change the name field to be something like:

 

 <apex:outputLink value="/{!Account.id}">{!Account.name}</apex:outputLink>

 

CharlieLangCharlieLang

would be so much easier if i could do this

 

<apex:outputLink value="{!contact.link}">{!contact.account.name}</apex:outputLink>

 

bob_buzzardbob_buzzard

Is contact.link available?  I though that was just for html templates.

CharlieLangCharlieLang

unfortunately i think it is just for templates :-(

bob_buzzardbob_buzzard

The alternative is:

 

<apex:outputLink value="{!URLFOR($Action.Contact.View, contact.id)}">{!contact.Account.Name}</apex:outputLink>  

 But that's not really any different IMHO.

CharlieLangCharlieLang

got it...

 

just adding the below works

 

<apex:outputLink value="/{!contact.id}">{!contact.account.name}</apex:outputLink>

 

Matt_Matt_

Thanks for the help bob!