I have a problem with a Visualforce and I am not being able to solve.

In the VF I have a form with two sections: one to fill the fields I'll use in the controller to create a quote and a dataTable with checkboxes to select the products I'll use to create the quote line items.

In the controller I have the wSelProducts wrapper class to process only the selected rows.

The problem is all of the variables related with the upper side of the form are passed as null to the controller.

The goal I could reach is on button click be able to create to create quote and quote line items. I have tried many unsuccesfully ways to reach that:

  • Two forms: one for quote and other one for dataTable and the button in dataTable form => the dataTable is succesfully processed but the quote fields are obviously null in the controller
  • One Form: one form for both sections means the method associated to the button is not longer executed, and I can not understand the reason.

Could you please help me on that, I am getting crazy:

Visualforce Code:

<apex:page showHeader="true" sidebar="true" standardController="Opportunity" extensions="CreateQuotePageController" docType="html-5.0">
    <apex:form id="QuoteForm">

        <apex:sectionHeader title="Quote" subtitle="New Quote"/>

      <apex:pageBlock id="pgBlock" title="Quote">

          <apex:pageBlockSection id="quoteInfo" title="Quote Information">

            <apex:pageBlockSection columns="1">

             <apex:inputText label ="Quote Name" value="{!qName}" id="qName"/>

             <apex:outputText label="Opportunity Name" value="{!opportunity.Name}" />

             <apex:outputText label="Account Name" value="{!opportunity.Account.Name}" />


           <apex:pageBlockSection columns="1"> 

             <apex:input type="date" label="Expiration Date" value="{!qExpirationDate}" />

             <apex:selectList size="1" label="Status">

                 <apex:selectOptions value="{!quoteStatusList}"/>

             <apex:inputtext label="Description" value="{!qDescription}" />


        <apex:pageBlockSection id="quoteTotals" title="Totals">

            <apex:pageBlockSection  columns="1">

             <apex:outputText label="Subtotal" value="{!qSubtotal}" />

             <apex:outputText label="Discount" value="{!qDiscount}" />

             <apex:outputText label="Total Price" value="{!qTotalPrice}" />

            <apex:pageBlockSection  columns="1"> 

             <apex:inputtext label="Tax" value="{!qTax}" />

             <apex:inputtext label="Shipping and Handling" value="{!qShippingHandling}" />

             <apex:inputtext label="Grand Total" value="{!qGrandTotal}" />


        <apex:pageBlockSection id="quoteContact" title="Prepared For" >

            <apex:pageBlockSection columns="1">

             <apex:inputtext label="Contact Name" value="{!qContactName}" />

             <apex:outputText label="Email" value="{!qEmail}" />


            <apex:pageBlockSection columns="1"> 

             <apex:inputtext label="Phone" value="{!qPhone}" />

             <apex:inputtext label="Fax" value="{!qFax}" />



        <apex:pageBlockSection id="quoteAddress" title="Quote Address">

            <apex:pageBlockSection  columns="1">        
             <apex:inputtext label="Bill To Name" value="{!qBillingName}" />

             <apex:inputtext label="Bill To Street" value="{!qBillingStreet}" />

             <apex:inputtext label="Bill To Zip/Postal Code" value="{!qBillingPostalCode}" />

             <apex:inputtext label="Bill To City" value="{!qBillingCity}" />

             <apex:inputtext label="Bill To State/Province" value="{!qBillingState}" />

             <apex:inputtext label="Bill To Country" value="{!qBillingCountry}" />

            <apex:pageBlockSection  columns="1">                 
             <apex:inputtext label="Ship To Name" value="{!qShippingName}" />

             <apex:inputtext label="Ship To Street" value="{!qShippingStreet}" />

             <apex:inputtext label="Ship To Zip/Postal Code" value="{!qShippingPostalCode}" />

             <apex:inputtext label="Ship To City" value="{!qShippingCity}" />

             <apex:inputtext label="Ship To State/Province" value="{!qShippingState}" />

             <apex:inputtext label="Ship To Country" value="{!qShippingCountry}" />


    <!-- </apex:form> -->
    <!-- </div>
    <div class='prodShow'> -->
    <!-- <apex:form>  -->
        <apex:pageBlock title="Productos">

            <apex:selectList size="1" id="myFamilyInput" onchange="FamilyFilter()">
                <apex:selectOption itemvalue="0" itemlabel="Todos" />
                <apex:selectOptions value="{!prodFamilyList}"/>

            <apex:selectList size="1" id="mySubFamilyInput" onchange="SubFamilyFilter()">
             <apex:outputText>Sub Familia</apex:outputText>
                <apex:selectOption itemvalue="0" itemlabel="Todos" />
                <apex:selectOptions value="{!prodSubFamilyList}"/>


            <apex:dataTable width="100%" value="{!productList}" var="selProd" id="myTable" rowClasses="odd,even" styleClass="product-table" >

                <apex:column width="5%">
                    <apex:facet name="header">Sel.</apex:facet>
                    <apex:inputCheckbox id="checkBox" value="{!selProd.checkbox}">

                <apex:column width="10%">
                    <apex:facet name="header">Familia</apex:facet>
                    <apex:outputText value="{!selProd.wSelProd.Product2.Family}" />

                <apex:column width="10%">
                    <apex:facet name="header">SubFamilia</apex:facet>
                    <apex:outputText value="{!selProd.wSelProd.Product2.Product_Sub__c}"/>

                <apex:column width="30%">
                    <apex:facet name="header">Name</apex:facet>
                    <apex:outputText value="{!selProd.wSelProd.Name}"/>

                <apex:column width="10%">
                    <apex:facet name="header">UnitPrice</apex:facet>
                    <apex:outputText id="precio" value="{!selProd.wSelProd.UnitPrice}"/>

                <apex:column width="10%">
                    <apex:facet name="header">Cantidad</apex:facet>
                    <apex:inputText id="cantidad" value="{!selProd.cantidad}">

                <apex:column width="10%">
                    <apex:facet name="header">Precio</apex:facet>
                    <apex:outputText id="precioCantidad">

                <apex:column width="10%">
                    <apex:facet name="header">DescuentoTotal</apex:facet>
                    <apex:inputText id="descuento" value="{!selProd.descuento}">

                <apex:column width="10%">
                    <apex:facet name="header">Coste con Dto</apex:facet>
                    <apex:outputText id="precioDescuento">


            <div id="totalPanel">
                <apex:outputLabel value="Cantidad Total" for="cantidadTotal"/>
                <apex:outputText label="Cantidad Total" id="cantidadTotal" />
                <apex:outputLabel value="Descuento" for="dtoTotal"/>
                <apex:outputText label="Descuento" id="dtoTotal" />
                <apex:outputLabel value="Cantidad con Descuento" for="cantidadDto"/>
                <apex:outputText label="Cantidad con Descuento" id="cantidadDto" />
                <apex:commandButton value="Crear Quote" action="{!processSelectedQLI}"/>


And The Controller:

    public class CreateQuotePageController {
    public Opportunity oppActual{get;set;}

    //public QuoteLineItem qli {get;set;}
    public list<SelectOption> prodFamilyList {get;set;}
    public list<SelectOption> prodSubFamilyList {get;set;}
    public list<SelectOption> quoteStatusList   {get;set;}

    //Our collection of the class/wrapper objects 
    public list<wSelProducts> productList {get;set;}

    //Creación de la quote
    //public list<wQuote> wq {get;set;}
    public Quote q {get;set;}

    public String qName {get;set;}
  public String qAccount {get;set;}
  public Date qExpirationDate {get;set;}
  public String qStatus {get;set;}
  public String qDescription {get;set;}

  public String qSubtotal {get;set;}
  public String qDiscount {get;set;}
  public String qTotalPrice {get;set;}

  public Decimal qTax {get;set;}
  public Decimal qShippingHandling {get;set;}
  public String qGrandTotal {get;set;}
  public Contact qContactName {get;set;}
  public String qEmail {get;set;}
  public String qPhone {get;set;}
  public String qFax {get;set;}
  public String qBillingName {get;set;}
  public String qBillingStreet {get;set;}
  public String qBillingPostalCode {get;set;}
  public String qBillingCity {get;set;}
  public String qBillingState {get;set;}
  public String qBillingCountry {get;set;}
  public String qShippingName {get;set;}
  public String qShippingStreet {get;set;}
  public String qShippingPostalCode {get;set;}
  public String qShippingCity {get;set;}
  public String qShippingState {get;set;}
  public String qShippingCountry {get;set;}

    public CreateQuotePageController(ApexPages.StandardController Opportunity) {

        oppActual =  new Opportunity();
        this.oppActual = (Opportunity)Opportunity.getRecord();



    public void getProductList(){

        productList = new list<wSelProducts>();
        for(PriceBookEntry selProd:[select Name,Id, PriceBook2Id, Product2Id, ProductCode,UnitPrice, UseStandardPrice,Product2.Family,Product2.Product_Sub__c, Product2.DescuentoMax__c from PriceBookEntry where UseStandardPrice = true]){
            productList.add(new wSelProducts(selProd));

        //system.debug('productList: ' + productList);

    public void getProductFamilyInfo(){

        prodFamilyList = new List<SelectOption>();

        Schema.DescribeFieldResult fieldResult = Product2.Family.getDescribe();
        List <Schema.PicklistEntry> ple = fieldResult.getPicklistValues();

        for(Schema.PicklistEntry f: ple){
            //prodFamilyList.add(new SelectOption(f.getValue(),f.getLabel()));
            prodFamilyList.add(new SelectOption(f.getValue(),f.getLabel()));

        //system.debug('prodFamilyList' + prodFamilyList);
        prodSubFamilyList = new List<SelectOption>();
        Schema.DescribeFieldResult fieldResult2 = Product2.Product_Sub__c.getDescribe();
        List<Schema.PicklistEntry> ple2 = fieldResult2.getPicklistValues();
        for(Schema.PicklistEntry f2: ple2){
            //prodFamilyList.add(new SelectOption(f.getValue(),f.getLabel()));
            prodSubFamilyList.add(new SelectOption(f2.getValue(),f2.getLabel()));

    public void getQuoteStatus(){
        quoteStatusList = new List<SelectOption>();
        Schema.DescribeFieldResult fieldResult = Quote.Status.getDescribe();
        List<Schema.PicklistEntry> ple = fieldResult.getPicklistValues();

        for(Schema.PicklistEntry f:ple){
            quoteStatusList.add(new SelectOption(f.getValue(),f.getLabel()));


    public void getQuoteFields(){

        q = new Quote();
    q.Name = qName;

    //q.Account = oppActual.Account.Name;
    q.ExpirationDate = qExpirationDate;
        q.Status = qStatus;
        q.Description = qDescription;

        q.Tax = qTax;
        q.ShippingHandling = qShippingHandling;

        q.Contact = qContactName;
        q.Email = qEmail;
        q.Phone = qPhone;
        q.Fax = qFax;
        q.BillingName = qBillingName;
        q.BillingStreet = qBillingStreet;
        q.BillingPostalCode = qBillingPostalCode;
        q.BillingCity = qBillingCity;
        q.BillingState = qBillingState;
        q.BillingCountry = qBillingCountry;
        q.ShippingName = qShippingName;
        q.ShippingStreet = qShippingStreet;
        q.ShippingPostalCode = qShippingPostalCode;
        q.ShippingCity = qShippingCity;
        q.ShippingState = qShippingState;
        q.ShippingCountry = qShippingCountry;

        q.Opportunity = oppActual;

    system.debug('Quote a crear: ' + q);

    insert q;

    //código que se ejecuta al pulsar el botón en la VF
    public PageReference processSelectedQLI (){

        system.debug('estoy ejecutandome al pulsar el boton');

        //create a list of the products selected
        List<wSelProducts> selProducts = new list<wSelProducts>();

        //We will cycle through our list of wQuoteLineItem and will check to 
        //see if the selected property is set to true, if it is we add the 
        for(wSelProducts product: productList ){
            if(product.checkbox == true){

        //Now we have our list of selected products and can perform any type of logic
        System.debug('Productos seleccionados...');
    for(wSelProducts selProduct: selProducts) {

    //Creación de la quote

    productList=null; // we need this line if we performed a write operation  because getContacts gets a fresh list now
    return null;


    //Wrapper container class: is a class, a data structure, or an abstract 
    //data type whose instances are collections of other objects. 
    public class wSelProducts {
        //Los datos que necesito pasar desde la table de la página son los
        //quote line items

        public PriceBookEntry wSelProd {get;set;}
        public Boolean checkbox {get;set;}
        public Integer cantidad {get;set;}
        public Integer descuento {get;set;}

        //This is the contructor method. When we create a new cContact object we pass a 
        //Contact that is set to the con property. We also set the selected value to false
        //public wSelProducts(PriceBookEntry selProd, Integer cantidad, Integer descuento, boolean checkbox){
        public wSelProducts(PriceBookEntry selProd){
            wSelProd = selProd;
            checkbox = false;
            cantidad = cantidad;
            descuento = descuento;



1 Answer 1


The solution is to keep only one form in order to have all the inputs from the VFP in the Controller.

In your code you are binding a String to a field of type "Contact"

<apex:inputtext label="Contact Name" value="{!qContactName}" />

That's why the button is no more working

  • Awesome Akram G!!! It is working now, but I am not able to pass the contact to the controller. I have created in opportunity a lookupfield with filter to show only the contacts related with the account. Once the user selects it this field and send the form the contact info is passed as null, so the quote is always created with contact info empty.
    – Tere
    Nov 13, 2017 at 13:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .