You need to sign in to do that
Don't have an account?
BeautifulDrifter
Help with Updating related records in Pageblocktable
Ok...so I am relatively new to this and have hit a wall. That being said, I have tried this a few way. I'm sure this will end up being something minor.
Basically, I am creating a questionaire, and breaking the questions out by category. I have the data and have it rendering correctly in VF. The issue is with trying to update the answers that are entered. Also, please note that the answers are dependent picklists. Below is an image of the page, and my two primary attempts at this. You may see some random extra code/buttons from me trying different things to update the data. I just need to update records with the entered answers within the VF page.
First try:
APEX:
Ok Ok. Got it, Salesforce isn't going to make this simple. So, I do a little research, and the natural first response to a post like this would be WRAPPER CLASS!
So, I went and wrote (copy/paste/tweaked) a wrapper, it renders correctly, but I can't figure out how to update the values. See below.
APEX:
Visualforce:
<apex:selectList value="{!wd.Answer}" id="answer" /> | Doesn't render as picklist
<apex:selectList value="{!wd.det.Answer__c}" id="answer" /> | Can't figure out how to update the value
I also tried actionsupport and passing params from the page for both onchange and onblur. I feel like this has become way more complicated than it should be. The one thing I DO NOT want to do is put a save button on each individual line of the table so every time someone answers a question they then have to save it.
Any help would be imensely appreciated as this is a sticking point that I need to work to move forward with what I am building.
Thanks in advance!
Basically, I am creating a questionaire, and breaking the questions out by category. I have the data and have it rendering correctly in VF. The issue is with trying to update the answers that are entered. Also, please note that the answers are dependent picklists. Below is an image of the page, and my two primary attempts at this. You may see some random extra code/buttons from me trying different things to update the data. I just need to update records with the entered answers within the VF page.
First try:
APEX:
public class CatDeetsEx { Public List<PSQ_Category__c> CategoriesList {get;set;} Public List<PSQ_Detail__c> DetailsList {get;set;} private ApexPages.StandardController stdCtrl {get; set;} public CatDeetsEx(ApexPages.StandardController std) { stdCtrl=std; setDeetsList(); } Private void SetDeetsList() { CategoriesList = [Select Id,Name, (select Id,PSQ_Category__c,PSQ_Header__c,Pick_List_Type__c ,Answer__c,Question__c from PSQ_Details__r ) from PSQ_Category__c where Id in (select PSQ_Category__c from PSQ_Detail__c where PSQ_Header__c=:stdCtrl.getId())]; } Public PageReference saveAll(){ update CategoriesList.PSQ_Details__r; } }VisualForce:
<apex:pageBlock > <apex:repeat value="{!CategoriesList}" var="cl"> <apex:pageBlockSection title="{!cl.Name}" id="catSection"> <apex:pageBlockTable id="detsTable" value="{!cl.PSQ_Details__r}" var="dl"> <apex:column value="{!dl.Question__c}" /> <apex:column > <apex:inputField value="{!dl.Pick_List_Type__c}" id="ParentPL" style="display:none" /> </apex:column> <apex:column > <apex:inputField value="{!dl.Answer__c}" id="deetAnswer" /> <apex:actionSupport event="onchange" action="{!updateAnswer}" rerender="dets"/> <apex:param assignTo="{!RecToUpd}" value="{!dl.Id}"/> <apex:param assignTo="{!updAnswer}" value="{!dl.Answer__c}"/> </apex:column> </apex:pageBlockTable> </apex:pageBlockSection> <apex:commandButton value="Save" action="{!saveAll}" reRender="catBlockSection"/> </apex:repeat> </apex:pageBlock>Error: Initial term of field expression must be a concrete SObject: List<PSQ_Category__c>
Ok Ok. Got it, Salesforce isn't going to make this simple. So, I do a little research, and the natural first response to a post like this would be WRAPPER CLASS!
So, I went and wrote (copy/paste/tweaked) a wrapper, it renders correctly, but I can't figure out how to update the values. See below.
APEX:
public class CatWrapExt { private ApexPages.StandardController stdCtrl {get; set;} public CatWrapExt(ApexPages.StandardController std) { stdCtrl=std; CatWrapExt(); } private List<PSQ_Category__c> tempcat = new List<PSQ_Category__c>(); private List<PSQ_Detail__c> tempD = new List<PSQ_Detail__c>(); private List<PSQ_Question__c> tempQ = new List<PSQ_Question__c>(); private Map<ID,List<PSQ_Detail__c>> catdetMAP = new Map<ID,List<PSQ_Detail__c>>(); private Set<ID> catIDs = new Set<ID>();//category ids to get details from public List<wrapper> wrapout {get; set;} //constructor public void CatWrapExt(){ wrapout = new List<wrapper>(); } //wrapper 1 class wrapper{ public PSQ_Category__c cat {get; set;} //List of wrappers public List<wrapper2> dets {get; set;} public wrapper(){ if(cat==null){cat = new PSQ_Category__c();}//initialize the category holder if(dets==null){dets = new List<wrapper2>();}//initialize the wrapper listholder } } //wrapper 2 - the sub-wrapper class wrapper2{ public PSQ_Detail__c det {get; set;} Public String Answer {get;set;} //public List<Product2> detprods {get; set;} public wrapper2(PSQ_Detail__c det,string Answer ){ if(det==null){det = new PSQ_Detail__c();}//initialize the Detail holder } public void updateDets(){ //list<psq_detail__c> detUpdate = New List <psq_detail__c>(); update det; } } public PageReference buildwrapper() { tempcat = [select id,name from PSQ_Category__c where Id in (Select PSQ_Category__c from PSQ_Record_Category__c where PSQ_Header__c = :stdCtrl.getId() AND Need__c = True) ]; for(PSQ_Category__c c:tempcat){catIDs.add(c.id);} tempD = [select Id,Detail_Question__c,Question__c,Pick_List_Type__c,Answer__c from PSQ_Detail__c where PSQ_Header__c =:stdCtrl.getId()]; for(PSQ_Detail__c d: TempD){ tempQ = [select Id,PSQ_Category__c from PSQ_Question__c where Id = :d.Detail_Question__c]; for (PSQ_Question__c q: TempQ){ if(catdetMap.containsKey(q.PSQ_Category__c)){ catdetMap.get(q.PSQ_Category__c).add(d);//adds detail for this category to the det list in the map }else{ catdetMap.put(q.PSQ_Category__c,new List<PSQ_Detail__c>{d});//adds new detail list for this category to the map } } } for(PSQ_Category__c cc:tempcat){ wrapper tmpwrapper = new wrapper(); tmpwrapper.cat=cc; List<wrapper2> t2 = new List<wrapper2>(); for(PSQ_Detail__c dd:catdetMap.get(cc.id)){ wrapper2 twrap2 = new wrapper2(dd ,dd.Answer__c); twrap2.det=dd; twrap2.Answer=dd.Answer__c; t2.add(twrap2); } tmpwrapper.dets=t2; wrapout.add(tmpwrapper); } return null; } }
Visualforce:
<apex:repeat value="{!wrapout}" var="w"> <apex:pageBlockSection title="{!w.cat.name}" id="catBlockSection"> <hr/> <apex:outputText value="" /> <apex:pageBlockTable id="detsBT" value="{!w.dets}" var="wd"> <apex:column value="{!wd.det.Question__c}" /> <apex:column > <apex:inputField value="{!wd.det.Pick_List_Type__c}" id="ParentPicklist" style="display:none" /> </apex:column> <apex:column > <apex:selectList value="{!wd.Answer}" id="answer" /> <apex:selectOptions value="{!level1items}"/> <apex:actionSupport event="onblur" action="{!updateAnswer}" rerender="dets"/> <apex:param assignTo="{!RecToUpd}" value="{!wd.det.Id}"/> <apex:param assignTo="{!updAnswer}" value="{!wd.det.Answer__c}"/> </apex:column> </apex:pageBlockTable> </apex:pageBlockSection> <apex:commandButton value="Save" action="{!updateTableAnswers}" reRender="catBlockSection"/> </apex:repeat>For the wrapper, the issue is I can't update the answers without defining them in the constructor. But if I define them in the constructor and then reference them in the VF page, the drop down does not render since the type string.
<apex:selectList value="{!wd.Answer}" id="answer" /> | Doesn't render as picklist
<apex:selectList value="{!wd.det.Answer__c}" id="answer" /> | Can't figure out how to update the value
I also tried actionsupport and passing params from the page for both onchange and onblur. I feel like this has become way more complicated than it should be. The one thing I DO NOT want to do is put a save button on each individual line of the table so every time someone answers a question they then have to save it.
Any help would be imensely appreciated as this is a sticking point that I need to work to move forward with what I am building.
Thanks in advance!
<apex:selectList value="{!strSelectedProductId}" size="1" id="productsSL" disabled="{!!ISNULL(objCafe.Id)}" onchange="assignCafePrice(this.value);">
<apex:selectOptions value="{!lstProductsByCategory}"/>
</apex:selectList>
and action function:
<apex:actionFunction name="assignCafePrice" action="{!assignCafePrice}" status="status" reRender="price, pgMsgs" immediate="true">
<apex:param name="selectedProduct" value="" assignTo="{!strSelectedProductId}"/>
</apex:actionFunction>
So you can try something like this:
<apex:inputField value="{!dl.Answer__c}" onchange=dummyMethod( '{!dl.Id}',this.value); > </apex:inputField>
actionFunction:
<apex:actionFunction name="dummyMethod" action="{!updateA}" reRender="dets" immediate="true">
<apex:param name = "p1" assignTo="{!RecordToUpdate}" value=""/> <apex:param name = "p2" assignTo= "{!updatedAnswer}" value=""/>
</apex:actionFunction>
All Answers
<apex:inputField value="{!wd.det.Answer__c}">
<apex:actionSupport event="onchange"
action="{!updateAnswer}"
rerender="dets">
<apex:param name="p1" assignTo="{!RecToUpd}" value="{!wd.det.Id}"/>
<apex:param name="p2" assignTo="{!updAnswer}" value="{!wd.det.Answer__c}"/>
</apex:actionSupport>
</apex:inputField>
public String RecToUpd {get;set;}
public String updAnswer {get;set;}
public void updateAnswer()
{
system.debug('==RecToUpd=='+RecToUpd);
system.debug('==updAnswer=='+updAnswer);
PSQ_Detail__c objDet = new PSQ_Detail__c(Id = RecToUpd, Answer__c = updAnswer);
update objDet;
}
Not sure whether above works, but you can give a try.
I changed the answer on one of the questions from "Yes" to "No". For some reason it is pulling the old value, not the new one. Any more help on this would be great.
15:05:57:085 USER_DEBUG [55]|DEBUG|==RecToUpdate==a0G41000003evjrEAA
15:05:57:085 USER_DEBUG [56]|DEBUG|==updatedAnswer==Yes
<apex:selectList value="{!strSelectedProductId}" size="1" id="productsSL" disabled="{!!ISNULL(objCafe.Id)}" onchange="assignCafePrice(this.value);">
<apex:selectOptions value="{!lstProductsByCategory}"/>
</apex:selectList>
and action function:
<apex:actionFunction name="assignCafePrice" action="{!assignCafePrice}" status="status" reRender="price, pgMsgs" immediate="true">
<apex:param name="selectedProduct" value="" assignTo="{!strSelectedProductId}"/>
</apex:actionFunction>
So you can try something like this:
<apex:inputField value="{!dl.Answer__c}" onchange=dummyMethod( '{!dl.Id}',this.value); > </apex:inputField>
actionFunction:
<apex:actionFunction name="dummyMethod" action="{!updateA}" reRender="dets" immediate="true">
<apex:param name = "p1" assignTo="{!RecordToUpdate}" value=""/> <apex:param name = "p2" assignTo= "{!updatedAnswer}" value=""/>
</apex:actionFunction>
I think I am almost there. Now I am getting a NULL error for the Id. It isn't passing anything to the new method for the Id. Let me know if you can help! Again, thanks in advance.
So what about picklist value, is it coming proper?
Make sure RecordToUpdate is STring and public get set
Ok...so I got it working. So, I guess it needed a rerender for some reason. Without the rerender it didn't pass the variable correctly. Weird. Anyways, Thanks for your help. Below is the code, and I didn't have to use a wrapper which was a plus.