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
The new LearnerThe new Learner 

List controllers are not supported for OpportunityLineItem

Hi Experts,

We have requirment where we need to replace Opportunity Proudct with the standard object oportunity product object, so i have edited entire controller code
but problem here is that when i replace stadnardcontroller with the OpportunityLineItem in the visualforce page its not allowing me to work its throwing an error called "Error: List controllers are not supported for OpportunityLineItem    ", 
can anyone help me out, how to fix this issue. 
 
Vf page: 
<apex:page standardController="Product__c" recordSetVar="oppProds" extensions="ProductController" showHeader="false" standardStylesheets="true" sidebar="false"
  docType="html-5.0">
   
    <body>
        <apex:form id="frm">
            <div align="center">
                <div class="h1Div" >
                    <input type="button" id="btnBack1" value="Back" class="sf1buttonSFBlue backButtonControlClass" onClick="javascript: goBack();" style="float: left;margin-top: -5px;margin-right: 15px;height: 35px;"/>
                    <h1>Opportunity Products</h1>
                    <img src="{!$Resource.SF1HeaderLogoSmall}" style="float:right;width: 100px;"/>
                </div>
                <br/>
                <apex:pageMessages id="MESSAGES"/>
            </div>
            
            <div class="sf1divBlock">
                <div class="sf1headerLabel">
                    <apex:outputLabel value="{!cOpp.Name}" style="margin-left: 5px;"/>
                </div>
                <br/>
                <apex:outputPanel id="OPPPRODPANEL">
                    <table id="OPPPRODTABLE" class="sf1Table" style="width:100%;">
                        <thead>
                            <tr>
                                <th width="50%"> Product </th>
                                <th width="12%"> Include in next quote </th>
                                <th width="22.5%"> Quantity </th>
                                <th width="22.5%"> Requested Price </th>
                                <th class="DMLActions" width="5%"> Action </th>
                            </tr>
                        </thead> 
                        <tbody>
                            <apex:variable var="rowClass" value="odd"/>
                            <apex:variable var="rowNum" value="{!0}"/> 
                            <apex:repeat value="{!clstOppProds}" var="oppProd">
                                <tr class="{!rowClass}">
                                    <td>
                                        <div class="scrollable-dropdown-menu">
                                            <input type="text" id="prodName{!rowNum}" name="prodName{!rowNum}" class="sf1Input"/>
                                        </div>
                                        <script>
                                            //Initialize the type ahead
                                            var prodName{!rowNum} = jQuery('#prodName{!rowNum}');
                                            if(prodName{!rowNum}){
                                                prodName{!rowNum}.typeahead(
                                                    {
                                                        minLength: 3,
                                                        highlight: true
                                                    },
                                                    {
                                                        limit: 999,
                                                        display: 'value',
                                                        source: function(searchText, syncCallback, asyncCallback) {
                                                            searchText = searchText.split('\\').join('\\\\');
                                                            searchText = searchText.split('\'').join('\\\'');
                                                            var sObj = new SObjectModel.Product2();
                                                            sObj.retrieve({ 
                                                                where:{
                                                                    or:{
                                                                        Name: {like: searchText + '%'},
                                                                        or:{
                                                                            Description: {like: searchText + '%'},
                                                                            Product2: {like : searchText + '%'}
                                                                        }
                                                                    },
                                                                    and:{
                                                                        Active__c: {eq: true},
                                                                        or:{
                                                                            RecordTypeId: {eq: '{!ProductRTId}'},
                                                                            and:{
                                                                                Status__c: {eq: 'Approved'},
                                                                                Product__c: {eq: ''}
                                                                            }
                                                                        }
                                                                    }
                                                                },
                                                                orderby: [{Name: 'ASC'}],
                                                                limit:999},
                                                                function(err,records){
                                                                    if(err){
                                                                        alert(err);
                                                                    } else {
                                                                        var dataList = [];
                                                                        var maxLength = 1;
                                                                        jQuery.each(records, function(index, record){
                                                                            dataList.push({
                                                                                id: record.get('Id'),
                                                                                value: jQuery('<div/>').html(record.get('Name')).text(),
                                                                                code: jQuery('<div/>').html(record.get('Type_Code__c')).text(),
                                                                                desc2: jQuery('<div/>').html(record.get('Description')).text()
                                                                            });
                                                                        });
                                                                        asyncCallback(dataList);
                                                                    }
                                                                }
                                                            ) 
                                                        },
                                                        templates: {
                                                            suggestion: function (data) {
                                                                var desc = data.value;
                                                                if(data.desc2) desc += ' - ' + data.desc2;
                                                                return '<div><table class="tt-table"><tr><td class="tt-table-td1">' + desc + '</td><td class="tt-table-td2">' + data.code + '</td></tr></table></div>';
                                                            }
                                                        }
                                                    }
                                                ).on('typeahead:selected', function (object, datum) {
                                                    setProd({!rowNum},datum.id,datum.value);
                                                }).on('typeahead:autocompleted', function (object, datum) {
                                                    setProd({!rowNum},datum.id,datum.value);
                                                }).on('typeahead:change', function (event, data) {
                                                    //Reset the fields to blank
                                                    
                                                });
                                            }
                                            prodName{!rowNum}.typeahead('val', '{!JSENCODE(oppProd.Product__r.Name)}');
                                        </script>
                                    </td>
                                    
                                    <td>
                                        <apex:inputField value="{!oppProd.Next_Quote__c}" style="width:30px; height:20px;"/>
                                    </td>
                                    <td>
                                        <apex:inputField value="{!oppProd.Quantity__c}" styleClass="sf1Input"/>
                                    </td>
                                    <td>
                                        <apex:inputField value="{!oppProd.Price__c}" styleClass="sf1Input"/>
                                    </td>
                                    <td valign="top" class="DMLActions">
                                        <input type="button" id="btnDelete{!oppProd.id}" class="sf1buttonDelete" value="" onClick="removeRow('{!rowNum}');" />
                                    </td>
                                </tr>
                                <apex:variable var="rowClass" value="{!IF(rowClass == 'odd','','odd')}"/> 
                                <apex:variable var="rowNum" value="{!rowNum + 1}"/> 
                            </apex:repeat>
                        </tbody>
                    </table>
                </apex:outputPanel>
                <table class="sf1InputTableTwoCol">
                    <tr>
                        <td>
                            <input type="button" id="btnBack" class="sf1buttonSFBlue" value="Back" onClick="goBack();" />
                            <input type="button" id="btnAddNew" class="sf1buttonSFBlue" value="Add New" onClick="addNew();" />
                            <input type="button" id="btnSave" class="sf1buttonSFBlue" value="Save" onClick="doSave();" />
                        </td>
                    </tr>
                </table>
            </div>
            
            <apex:actionFunction name="setProd" action="{!setProd}" reRender="MESSAGES" status="status">
                <apex:param name="p1" value="" assignTo="{!selectedRowNum}"/>
                <apex:param name="p2" value="" assignTo="{!selectedRowProdId}"/>
                <apex:param name="p3" value="" assignTo="{!selectedRowProdName}"/>
            </apex:actionFunction>
            <apex:actionFunction name="removeRow" action="{!removeRow}" reRender="MESSAGES,OPPPRODPANEL" status="status">
                <apex:param name="p1" value="" assignTo="{!selectedRowNum}"/>
            </apex:actionFunction>
            <apex:actionFunction name="goBack" action="{!cancel}" reRender="MESSAGES" status="status"/>
            <apex:actionFunction name="doSave" action="{!doSave}" reRender="MESSAGES" status="status"/>
            <apex:actionFunction name="addNew" action="{!addNew}" reRender="MESSAGES,OPPPRODPANEL" status="status"/>
            
            <apex:actionstatus id="status">
                <apex:facet name="start">
                    <div class="waitingSearchDiv" id="el_loading" style="background-color: #fbfbfb;height: 100%;opacity:0.65;width:100%;">
                        <div class="waitingHolder" style="top:220px;">
                            <img class="waitingImage" src="{!$Resource.Salesfroce1Loading}" title="Processing..." />
                        </div>
                    </div>
                </apex:facet> 
            </apex:actionstatus>
        </apex:form>
    </body>
</apex:page>


Apex class:

public class ProductController {
    public Opportunity cOpp {get;set;}
    public Integer selectedRowNum {get;set;}
    public String selectedRowProdId {get;set;}
    public String selectedRowProdName {get;set;}
    public List<OpportunityLineItem> clstOppProds {get;set;}
    public List<OpportunityLineItem> clstDelOppProds {get;set;}
    public String getJDEProductRTId(){
        return [SELECT Id FROM RecordType WHERE SObjectType = 'Product2' AND Name = 'New Products' LIMIT 1].get(0).Id;
    }
	
	   public ProductController(ApexPages.StandardSetController ssc) {
        selectedRowNum = null;
        selectedRowProdId = null;
        selectedRowProdName = null;
        String oppId = ApexPages.currentPage().getParameters().get('id');
        cOpp = null;
        for(Opportunity o : [SELECT Id,Name FROM Opportunity WHERE Id = :oppId]) cOpp = o;
        clstOppProds = new List<OpportunityLineItem>();
        clstDelOppProds = new List<OpportunityLineItem>();
        if(oppId != null) clstOppProds = [SELECT Id,Opportunityid,Next_Quote__c,Product2id,Product2.Name,Quantity__c,Price__c FROM OpportunityLineItem WHERE Opportunityid = :oppId];
    }
	
	 public PageReference setProd(){
         PageReference pg = null;
         OpportunityLineItem op = clstOppProds.get(selectedRowNum);
         Product2 pt = new Product2(id=selectedRowProdId,name=selectedRowProdName);
         op.Product2id = selectedRowProdId;
         op.Product2.Name = pt.Name;
         return pg;
     }
	 
	 public PageReference removeRow(){
         PageReference pg = null;
         OpportunityLineItem op = clstOppProds.remove(selectedRowNum);
         if(op.Id != null) clstDelOppProds.add(op);
         return pg;
     }
	 
	   public PageReference addNew(){
         PageReference pg = null;
         clstOppProds.add(new OpportunityLineItem(Opportunityid=cOpp.Id));
         return pg;
     }
	 public PageReference doSave(){
         PageReference pg = null;
         SavePoint sp = Database.setSavePoint();
         try{
             delete clstDelOppProds;
             upsert clstOppProds;
             pg = new PageReference('/'+cOpp.Id);
         }catch(Exception e){
             Database.rollback(sp);
             Apexpages.addMessage(new Apexpages.Message(Apexpages.Severity.ERROR, e.getMessage()));
         }
         return pg;
     }
}

 
KrishnaAvvaKrishnaAvva
Hi,

Not all objects support list controllers - standard controller + recordSetVar(StandardSetController). You have to write a custom controller.

Regards,
Krishna Avva
The new LearnerThe new Learner
Hi Krishna,

I am little new to visual force pages and not able to do that , can you help me out please