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
tsalbtsalb 

Standard Layout VFpage insert cannot get ID

I'm not sure how to get my page to appear as a standard page layout visualforce insert. When accessing the page normally via url (/apex/page?rfpId=<record id>) it works fine. However when accessing via the salesforce url (naX.salesforce.com/<record ID>) the page layout insert errors "Content cannot be displayed: List has no rows for assignment to SObject"

 

I know this is an extension issue, but I'm not clear on where to make my edits so that my standard layout can access my visualforce page. 

 

The record where the VFpage Insert (Standard Layout) is, is the record ID that needs to be passed. I know it has something to do with getRecord(); but I'm not sure where to apply it.

 

EDIT: Ah, I need to add that this Page is rendered as a PDF.

 

Proposal Extension:

 

public with sharing class ProposalExtension {

    public String rfpId = ApexPages.currentPage().getParameters().get('rfpId'); 
    private final Proposal__c p;
    
    //Constructor for ProposalExtension	
    public ProposalExtension(ApexPages.StandardController pCon) {
        this.p = (Proposal__c)pCon.getRecord();
    }
	
	//Proposal used for vendor pages 
    Proposal__c rfp;
	
    public Proposal__c getRFP(){
    	rfp = [SELECT 
	    //Proposal Fields Examples
	    Id, Name, Contracting_Manager_Email__c
	    //Vendor (Contact) Fields Examples
	    Vendor__r.Name, Vendor__r.Account.Name
		
		FROM Proposal__c WHERE Id = :rfpId];	
		
		return rfp;	
    }      

}

 

 Sample VF page content:

Company:<apex:outputField value="{!rfp.Vendor__r.Account.Name}"/><br/>

 

Best Answer chosen by Admin (Salesforce Developers) 
tsalbtsalb

Actually. You cant insert a renderAs="PDF" page inside a standard page layout without butchering the page.

 

So, this visualforce page (placed in a standard layout) kills two birds with one stone. No controller work.

 

<apex:page standardController="Proposal__c">
<apex:iframe src="../apex/myPage?someId={!Proposal__c.Id}" frameborder="1" height="600" scrolling="yes"/>
</apex:page>

 

All Answers

tsalbtsalb

Actually. You cant insert a renderAs="PDF" page inside a standard page layout without butchering the page.

 

So, this visualforce page (placed in a standard layout) kills two birds with one stone. No controller work.

 

<apex:page standardController="Proposal__c">
<apex:iframe src="../apex/myPage?someId={!Proposal__c.Id}" frameborder="1" height="600" scrolling="yes"/>
</apex:page>

 

This was selected as the best answer
jwetzlerjwetzler

That's because when you access a record via naX.salesforce.com/<record ID>, the parameter that your <record ID> is stored as is "id", not "rfpId". We have no way of knowing that you want your id parameter to be called "rfpId". 

 

So you should be calling this instead:

    public String rfpId = ApexPages.currentPage().getParameters().get('rfpId'); 

And you should be accessing your page directly as /apex/page?id=<record id>

 

Although I don't understand why you're querying for your proposal when you already have it stored in 'p' via the getRecord() call...

tsalbtsalb

Yea, I saw that too. I'm a psuedo dev that has inherited this code - so I dont want to go back too much and redo all the pieces to !p.Field__c

 

I'm learning little by little.

 

Also, I've tried naX.salesforce.com/abc0001?rfpId=abc0001, with the visualforce page at the bottom (as an insert in a section) and it didnt work. Using the iframe method above works great though.

jwetzlerjwetzler

Well, you could always make your getRFP() method return p, instead of querying all over again. It will save you an API call.

 

Also what exactly are you trying to do? An iframe seems wholly unnecessary here. You can always use the action method on apex:page to redirect to the page you want.

tsalbtsalb

I'm trying to have all the items necessary on one page for the user experience / convenience.

 

On the page layout, there is a button at the top (JS Onclick) that approves the PDF (rendered now in an iframe - displayed on the same layout).

 

The button sets an approved date, which in turn performs some logic on the visualforce pdf (some fields get  toggled to rendered=true). So basically, they're approving the PDF then seeing the changes right away.

jwetzlerjwetzler

I see, so there's more to your page than just the iframe.

 

Anyway, I would really consider the returning p in your getRFP method. It will actually save you a ton of API calls since the way you have it written, every reference to RFP on your page will make an API call. At the very least you only want to run your SOQL query if rfp is null, so that it only gets called once per page render.

 

tsalbtsalb

So this?

 

I just tried this in sandbox, but it doesn't work.

 

public with sharing class ProposalExtension {

    public String rfpId = ApexPages.currentPage().getParameters().get('rfpId'); 
    private final Proposal__c p;
    
    //Constructor for ProposalExtension	
    public ProposalExtension(ApexPages.StandardController pCon) {
        this.p = (Proposal__c)pCon.getRecord();
    }
	
    //Proposal used for vendor pages 
    Proposal__c rfp;
	
    public Proposal__c getRFP(){
    	rfp = [SELECT 
	    //Proposal Fields Examples
	    Id, Name, Contracting_Manager_Email__c
	    //Vendor (Contact) Fields Examples
	    Vendor__r.Name, Vendor__r.Account.Name
		
	    FROM Proposal__c WHERE Id = :rfpId];	
		
	    return p;	//EDIT
    }      

}

 

If i wanted to make the changes you suggest - the original url would be ../apex/myPage?rfpId=<record id>

 

How would I assign it an Id afterwards?

jwetzlerjwetzler

Whoa. No I'm saying:

public with sharing class ProposalExtension {

    private final Proposal__c p;
    
    //Constructor for ProposalExtension	
    public ProposalExtension(ApexPages.StandardController pCon) {
        this.p = (Proposal__c)pCon.getRecord();
    }
	
    public Proposal__c getRFP(){
	    return p;
    }      

}
tsalbtsalb

SObject row was retrieved via SOQL without querying the requested field: Proposal__c.Sent_Date__c

 

/apex/myPage?Id=<record Id>

 


jwetzlerjwetzler

Okay... so I guess I'm not seeing a lot of your code.  You have a reference to this field somewhere in your controller but not on your page so it's not getting pulled in to the original standard controller query. The usual workaround for that is to just refer to it on your page and hide it, but I guess you can go back to your original solution, but with lazy loading so you don't make a bunch of unnecessary queries. I'm confused though because you don't even have Sent_Date__c in your original query in the getRFP() method so it makes no sense why you would get this error after making that change. Did you post an edited version of your query?

 

Anyway here's what I mean by only doing the query once.

 

public with sharing class ProposalExtension {

    public String rfpId = ApexPages.currentPage().getParameters().get('rfpId'); 
    private final Proposal__c p;
    
    //Constructor for ProposalExtension	
    public ProposalExtension(ApexPages.StandardController pCon) {
        this.p = (Proposal__c)pCon.getRecord();
    }
	
    //Proposal used for vendor pages 
    Proposal__c rfp;
	
    public Proposal__c getRFP(){
if (rfp == null) { rfp = [SELECT //Proposal Fields Examples Id, Name, Contracting_Manager_Email__c //Vendor (Contact) Fields Examples Vendor__r.Name, Vendor__r.Account.Name FROM Proposal__c WHERE Id = :rfpId]; } return rfp; } }
tsalbtsalb

Ah yes. Sorry, the entire extension is 450+ chars with test method. I only posted a snippet. The getRFP() method queries for quite a number of fields.

 

I appreciate all the help, I'll definitely update accordingly - I'm still learning best practices bit by bit