Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

I'm having difficulty with a VF page I am building.

The objects involved are Opportunity, and Job_Bag_Contact__c (Junction object between Opp. (MD) and Contact(LKP)).

Here is my VF:

<apex:page standardController="Opportunity" extensions="JobBagContacts">
<apex:sectionHeader title="Job Bag Edit" subtitle="{!Opportunity.name}"/>
    <apex:form >
        <apex:pageBlock title="Job Bag Edit">
            <apex:pageBlockButtons >
                <apex:commandButton action="{!save}" value="Save"/>
                <apex:commandButton action="{!delete}" value="Delete"/>
                <apex:commandButton action="{!cancel}" value="Cancel"/>
            </apex:pageBlockButtons>
            <apex:pageBlockSection columns="2" title="Job Bag Information">
            </apex:pageBlockSection>
            <apex:pageBlockSection columns="2" title="Project or Customer Name & Registration">
            </apex:pageBlockSection>
            <apex:pageBlockSection columns="2" title="Accounting / Logistics Information">
            </apex:pageBlockSection>
            <apex:pageBlockSection columns="2" title="Shipping">
            </apex:pageBlockSection>
            <apex:pageBlockSection columns="2" title="Shipping Back Order">
            </apex:pageBlockSection>
            <apex:pageBlockSection columns="2" title="Custom Information">
            </apex:pageBlockSection>
            <apex:pageBlockSection columns="2" title="Additional Information">
            </apex:pageBlockSection>
            <apex:pageBlockSection columns="2" title="Description Information">
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
    <apex:form >
        <apex:pageBlock title="Job Bag Contacts">
            <apex:variable value="{!0}" var="rowNumber" />
        <apex:outputPanel id="panelWithVar">
            <apex:variable value="{!0}" var="rowNumber" />
        </apex:outputPanel>
        <apex:pageBlockButtons >
            <apex:commandButton value="Add" action="{!addNewObject}" reRender="JobBagContacts,NewJobBagContacts,panelWithVar" immediate="true"/>
            <apex:commandButton value="Save" action="{!saveObjects}" reRender="JobBagContacts,NewJobBagContacts,panelWithVar" immediate="true"/>
            <apex:commandButton value="Cancel" action="{!cancelChanges}" reRender="JobBagContacts,NewJobBagContacts,panelWithVar" immediate="true"/>
        </apex:pageBlockButtons>
        <apex:pageBlockTable value="{!contacts}" var="contact" id="NewJobBagContacts">
            <apex:column headerValue="Name" title="Name" width="30%">
                <apex:inputField value="{!contact.Contact__c}"/>
            </apex:column>
            <apex:column headerValue="Account" title="Account">
                <apex:outputField value="{!contact.Contact__r.Account.Name}"/>
            </apex:column>
            <apex:column headerValue="Phone" title="Phone">
                <apex:outputField value="{!contact.Contact__r.Phone}"/>
            </apex:column>
            <apex:column headerValue="Email" title="Email">
                <apex:outputField value="{!contact.Contact__r.Email}"/>
            </apex:column>
            <apex:column headerValue="Title" title="Title">
                <apex:outputField value="{!contact.Contact__r.Title}"/>
            </apex:column>
            <apex:column headerValue="Primary?" title="Primary?" width="10%">
                <apex:inputField value="{!contact.Primary__c}"/>
            </apex:column>
        </apex:pageBlockTable>
        </apex:pageBlock>
    </apex:form>

and here is the controller extension:

public with sharing class JobBagContacts {

    public List<Job_Bag_Contact__c> objectsToInsert {get;set;}
    public Integer numberOfRowsToRemove {get;set;}
    Opportunity current {get;set;}

    public JobBagContacts(ApexPages.StandardController controller) {
        current = (Opportunity) controller.getRecord();
    }

    public List<Job_Bag_Contact__c> getContacts() {
        return [
            SELECT Contact__c, Contact__r.Account.Name, Contact__r.Phone, Contact__r.Email, Contact__r.Title, Primary__c
            FROM Job_Bag_Contact__c
            WHERE Opportunity__c = :current.Id
        ];
    }

    public PageReference addNewObject () {
        system.debug('current: ' + current);
        Job_Bag_Contact__c newObject = new Job_Bag_Contact__c (Opportunity__c = current.Id);
        system.debug('newObject: ' + newObject);
        objectsToInsert.add(newObject);
        return null;
    }

    public PageReference removeNewObject () {
        objectsToInsert.remove(numberOfRowsToRemove);
        return null;
    }

    public PageReference saveObjects () {
        if (objectsToInsert.size() > 0)
            upsert objectsToInsert;
        return null;
    }

    public PageReference cancelChanges () {
        return null;
    }

}

Basically it replicates the 'edit' page while allowing users to add, update or delete Job_Bag_Contact__c records on the same page.

Note, Opportunity has been re-labeled to Job Bag, it is not another custom object.

Thanks in advance for any help, I'm absolutely puzzled as to the cause of this error:

14:27:10.093 (93666000)|FATAL_ERROR|System.NullPointerException: Attempt to de-reference a null object

Class.JobBagContacts.addNewObject: line 23, column 1

share|improve this question

3 Answers 3

Try adding

      public JobBagContacts(ApexPages.StandardController controller) {
            current = (Opportunity) controller.getRecord();
            objectsToInsert = new  List<Job_Bag_Contact__c> ();
        }

Update : I have a shortcut for the implementation you are trying to do : Correct me if I am wrong : All you need is a page where the users can edit, delete, save and cancel ? Am I right ?
You can do this easily using $Action To restrict users from editing certain fields assign a diffrent page layout to them and make all the fields as readonly/make the fields not visible that way you do not have to write complex code and this code below does not require any controller : The retURL will return the page back to your original VF page on cancel and Saveurl will return it on saving the record.

Code :

<apex:commandlink value="Delete" action="{!URLFOR($Action.Opportunity.Delete,current.Id,[retURL="/apex/Vf_page?id="+current.Id])}">

for save: replace the value="Save" action="{!URLFOR($Action.Opportunity.Delete,current.Id,[retURL="/apex/Vf_page?id="+current.Id,saveURL="/apex/Vf_page?id="+current.Id])}">
share|improve this answer
    
No change I'm afraid, same error message. –  DavinC Dec 31 '12 at 17:08
    
which is this line 23 as per your code!!! –  rao Dec 31 '12 at 17:50
1  
are you getting a value for the "current" system debug??? another silly assumption are you providing the id on the page (ie)is your url like /apex/vfpage?id=006something ?? –  rao Dec 31 '12 at 17:54
    
Yes I'm providing the ID in the URL and there is a value for 'current' in the debug log. I'm not getting the error message anymore, but now nothing happens when I click the 'Add' button (it should be creating a new record and re-rendering the section). Any ideas? –  DavinC Dec 31 '12 at 18:37
1  
2 things i see 1) there is an immediate attribute which sometimes kills the error message 2) when u click the add button the "addNewObject" method has nothing but a "ObjectstoInsert" holder which is a list containing all the objects to insert. The "saveObjects" is the one that is upserting the data. All your add button would do is add the selected data to the list!!! –  rao Dec 31 '12 at 18:47

You have not initialized objectsToInsert list before using this.

You can do this in two ways -

1) Initialize at the time of declaration like -

public List<Job_Bag_Contact__c> objectsToInsert = new List<Job_Bag_Contact__c>();

and create getter and setter for this.

2) Initialize under constructor as @ rao has done -

    public JobBagContacts(ApexPages.StandardController controller) {
        current = (Opportunity) controller.getRecord();
        objectsToInsert = new  List<Job_Bag_Contact__c> ();
    }
share|improve this answer

Rao and Pramod have identified the issue for you and the reason for your null pointer. Here are some pointers to think. 1. You have your list objectsToInsert declared as a property and assuming that it would be instantiated when the visual force page loads. Well , properties behave independantly and cannot be controlled.

So the moral is If you use any list or collection, make sure you instantiate them either in the constructor or in the method where you use them. Then add the object and you should be good. You are also expecting the object to be inserted in the database. In your code you have just added it to the collection only. So use Database.insert to insert your collection and your record will be in the object.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.