0

I have a VF page that uses standard controller Account and an extension DonorSearchCon. When I select a Regional_Chapter_Name__c lookup field, from my VF page, I would like to query the record, and derive other field information for that record. Unfortunately, I get the following error:System.QueryException: List has no rows for assignment to SObject.

Here is my code VF Page:

<apex:inputField value="{!acc.Regional_Chapter_Name__c}">
                <apex:actionSupport event="onchange" 
                   action="{!regionLookup}"
                   status="status"/> 
</apex:inputfield>

Controller:

public with sharing class DonorSearchCon {
public Account acc {get;set;}
private ApexPages.StandardController stdCtrl;

    public donorSearchCon(ApexPages.StandardController std){
        stdCtrl = std;        
    }

    public void regionLookup(){
        Account acc=(Account) stdCtrl.getRecord();
       System.debug('acc:' +acc);
       Regional_Chapter__c regionInfo = [Select id, Regional_Chapter_Code__c from Regional_Chapter__c where Name=:acc.Regional_Chapter_Name__c];
        System.debug('acc.Regional_Chapter_Name__r' +regionInfo);
    }
}
0

There is an error in your query:

Select id, Regional_Chapter_Code__c from Regional_Chapter__c where id=:acc.Id

Specifically here:

from Regional_Chapter__c where id=:acc.Id

The Account Id will never be the same as the Regional_Chapter__c Id

Try something like this:

from Regional_Chapter__c where Name = :acc.Regional_Chapter_Name__c

Bonus Tip

I generally don't use stdCtrl.getRecord(). This will only pull in fields that you have defined on the page. While that may work for your case here, I would recommend a habit avoiding it.

I would also generally recommend a very minimal constructor. The one you have here is generally fine but I wouldn't put much more inside of it. Instead, I would add the action attribute to the VF page to call an init method: action="{!init}"

So the page would look like:

<apex:page standardController="Account" extension="DonorSearchCon" action="{!init}">
    <apex:pageMessages /> <!-- Used to display errors to the page -->
    <!-- Do not render the form if there is no account -->
    <apex:form rendered="{!NOT(ISBLANK(pageRecord))}">
        <apex:inputField value="{!acc.Regional_Chapter_Name__c}">
            <apex:actionSupport event="onchange" 
                action="{!getRegion}"
                status="status"/> 
        </apex:inputfield>
    </apex:form>
</apex:page>

Your extension would look like this:

public with sharing class DonorSearchCon {
    private ApexPages.StandardController stdCtrl;
    public Account pageRecord {get;set;}

    public donorSearchCon(ApexPages.StandardController std){
        this.stdCtrl = std;        
    }

    // We use init methods because there are some tasks that cannot be 
    // performed in the constructor. This method is less limited in what it can do
    // but still gets called before the page actually renders
    public void init() {
        this.pageRecord = getAccount(this.stdCtrl.getRecordId());

        if (this.pageRecord == null) {
            ApexPages.addMessage(new ApexPages.message(
                'No Account Found',
                ApexPages.Severity.FATAL
            ));
        }
    }

    private Account getAccount(Id recordId) {
        // Using a list here will prevent the List has no rows error
        // Instead, you will simply get an empty list.
        List<Account> accounts = [
            SELECT Id, Region_chapter_Name__c, 
                Regional_Chapter_Name__r.Regional_Chapter_Code__c
            FROM Account
            WHERE Id = :recordId
        ];

        // Check to make sure we have an account before trying to assign it
        return accounts.isEmpty() ? null : accounts[0];
    }

    public void getRegion(){
       // Using a list here will prevent the List has no rows error
       // Instead, you will simply get an empty list.
       // The important bit here is that Regional_Chapter_Name__c contains
       // the *Id* of the Regional_Chapter_Name__c record.
       // the Regional_Chapter_Name__r field contains the actual
       // Regional_Chapter_Name__c record and all of it's fields
       List<Regional_Chapter__c> regionInfos = [
           Select id, Regional_Chapter_Code__c 
           from Regional_Chapter__c 
           where Id = :pageRecord.Regional_Chapter_Name__c
       ];

       if (regionInfos.isEmpty()) {
           ApexPages.addMessage(new ApexPages.message(
               'No Region Found',
               ApexPages.severity.FATAL
           ));
       } else {
           this.pageRecord.Regional_Chapter_Name__r = regionInfos[0];
           this.pageRecord.Regional_Chapter_Name__c = regionInfos[0].Id;
       }
    }
}
| improve this answer | |
  • Thank you for the feedback. Actually, I already did, but now I am getting: System.QueryException: List has no rows for assignment to SObject. if I run a debug, I am not getting any results: public void regionLookup(){ Account acc=(Account) stdCtrl.getRecord(); System.debug('acc:' +acc); Regional_Chapter__c regionInfo = [Select id, Regional_Chapter_Code__c from Regional_Chapter__c where Name=:acc.Regional_Chapter_Name__c]; System.debug('acc.Regional_Chapter_Name__r' +regionInfo); } – Ivo Dimov May 23 '19 at 20:39
  • If you already did it then update your code in your question. – gNerb May 23 '19 at 20:40
  • I just did. Looks like my Account is not being instantiated. – Ivo Dimov May 23 '19 at 21:01
  • Is Regional_Chapter_Name__c a lookup field? – gNerb May 24 '19 at 15:03
  • Yes, it is a lookup field on the Account object, that looks into the Regional_Chapter__c object – Ivo Dimov May 24 '19 at 15:26

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.