You need to sign in to do that
Don't have an account?
Iterate without using repeat in visualforce
hello,
I have tables for sections,questions and response with master detail relationship between sction and question, question and response table. I want to display all of them with response under question and all questions under section.
Apex code
public class QuestionnaireFieldsReport
{
public List<Question_Template__c> questionsLists { get; set; }
public List<Section_Template__c > sectionsLists{ get; set; }
public List<Questionnaire_Response__c> QuestionResponse{get;set;}
public List<QuestionDisplay> listQuestWithOptions;
//create a new inner class
public class QuestionDisplay
{
public Question_Template__c newquestFormat{get;set;}
public List<Question_Template__c > qlistss {get;set;}
public List<Questionnaire_Response__c> rlistss{get;set;}
public Section_Template__c secObj{get;set;}
public QuestionDisplay(Section_Template__c sobj,List<Question_Template__c > ql,List<Questionnaire_Response__c> rl)
{
secObj= new Section_Template__c ();
qlistss =new List<Question_Template__c>();
rlistss= new List<Questionnaire_Response__c>();
this.secObj=sobj;
this.qlistss =ql;
this.rlistss=rl;
}
}//end inner class
public List<QuestionDisplay> getquestionsList()
{
Integer i=0;
listQuestWithOptions= new QuestionDisplay[]{};
accountId=System.currentPageReference().getParameters().get('accId');//to get the school or account id
//System.debug('!!!!!!!!!!!!!!!!~~~~~~~~~~~~~acct id from diff page :'+accountid);
sectionsLists = [Select Id, Name,status__c,Section_label__c,Order_No__c from Section_Template__c];
QuestionResponse=[Select id,Response__c,Question_Template__r.id,Question_Template__r.Question_Label__c,Account_to_Response__c,Questionnaire_Taker_user__c from Questionnaire_Response__c where Account_to_Response__c= :accountId] ;
for(integer w=0;w<sectionsLists.size();w++)
{
List<Question_Template__c > qlists= new List<Question_Template__c>();
List<Questionnaire_Response__c> rlists= new List<Questionnaire_Response__c>();
questionsLists = [SELECT Id,Section_Question__r.id,Question_Label__c,Question_Order_No__c FROM Question_Template__c where Section_Question__r.id=:sectionsLists[w].id order by Question_Order_No__c];
for(integer w1=0;w1<questionsLists.size();w1++)
{
Questionnaire_Response__c resp=new Questionnaire_Response__c();
if((QuestionResponse==null)||(QuestionResponse.size()==0))
{
rlists.add(resp);
qlists.add(questionsLists[w1]);
}
else
{
integer checkflag=0;
for(integer k=0;k<QuestionResponse.size();k++)
{
if(QuestionResponse[k].Question_Template__r.id==questionsLists[w1].id)
{
checkflag=1;resp=QuestionResponse[k];break;
}
}
rlists.add(resp);
qlists.add(questionsLists[w1]);
}
}
//r is reponse list and qlists is question list
listQuestWithOptions.add(new QuestionDisplay(sectionsLists[w],qlists,rlists) );
}
}
Visualforce code
I want the response and questions list to iterate alternatively
<apex:repeat value="{!questionsList}" var="section">
<apex:variable var="rlists" value="{!section.rlistss}"/>
<apex:pageBlockSection id="subsection" columns="1" title="{!section.secObj.Section_label__c}">
<apex:repeat value="{!section.qlistss}" var="qlist">
<apex:outputField value="{!qlist.Question_Label__c}" />
<apex:outputField value="{!rlists.Response__c}" /> <!-- this fails as i do not know how to iterate both together-->
<br> </br>
</apex:repeat>
Thanks
Apex code:
public with sharing class QuestionsList {
// Creates section List
public List<Sections> getSections(){
Map<Id, Sections> mapSections = new Map<Id, Sections>();
// Add Section Records
for (Section__c sec : [SELECT Id, Name FROM Section__c]){
mapSections.put(sec.Id, new Sections(sec));
}
// Add Question Records
for (Question__c ques : [SELECT Id, Name, Section__c FROM Question__c]){
// Add question records to section
Sections section = mapSections.get(ques.Section__c);
section.questions.add(ques);
// Here i added all the question Ids in to the map
section.response.put(ques.Id, new Answer__c());
mapSections.put(ques.Section__c, section);
}
// Add Answer Records
Map<Id, Answer__c> mapAnswer = new Map<Id, Answer__c>();
for (Answer__c ans : [SELECT Id,Name, Question__c, Question__r.Section__c FROM Answer__c]){
Sections section = mapSections.get(ans.Question__r.Section__c);
section.response.put(ans.Question__c, ans);
mapSections.put(ans.Question__r.Section__c, section);
}
return mapSections.values();
}
// Create an inner class
public class Sections{
public Section__c section {get; set;}
public Question__c[] questions {get; set;}
public Map<Id, Answer__c> response {get; set;}
public Sections(Section__c sec){
section = sec;
questions = new Question__c[]{};
response = new Map<Id, Answer__c>();
}
}
}
Visualforce
<apex:page Controller="QuestionsList" >
<apex:pageBlock title="Questions List" >
<apex:repeat value="{!Sections}" var="sec" >
<!-- display section -->
<apex:outputText value="{!sec.section.Name}" />
<apex:repeat value="{!sec.questions}" var="q" >
<!-- display questions -->
<apex:outputText value="{!q.Name}" />
<!-- display answer -->
<apex:outputText value="{!sec.response[q.Id].Name}"
rendered="{!IF(NOT(ISNULL(sec.response[q.Id])),'true','false')}" />
</apex:repeat>
</apex:repeat>
</apex:pageBlock>
</apex:page>
Hope, this will work for you.
All Answers
Hi,
Assume, I created 3 objects. Section, Question, Respone. Question has a master detail relationship with Section and Answer has master detail relationship with Quesiton. If you want to get the reponse for the particular question without using repeat,
Apex
public with sharing class QuestionsList {
// Creates section List
public List<Sections> getSections(){
Map<Id, Sections> mapSections = new Map<Id, Sections>();
// Add Section Records
for (Section__c sec : [SELECT Id, Name FROM Section__c]){
mapSections.put(sec.Id, new Sections(sec));
}
// Add Question Records
Map<Id, Sections> mapQuestions = new Map<Id, Sections>();
for (Question__c ques : [SELECT Id, Name, Section__c FROM Question__c]){
// Add question records to section
Sections section = mapSections.get(ques.Section__c);
section.questions.add(ques);
mapSections.put(ques.Section__c, section);
}
// Add Answer Records
Map<Id, Answer__c> mapAnswer = new Map<Id, Answer__c>();
for (Answer__c ans : [SELECT Id,Name, Question__c, Question__r.Section__c FROM Answer__c]){
Sections section = mapSections.get(ans.Question__r.Section__c);
section.response.put(ans.Question__c, ans);
mapSections.put(ans.Question__r.Section__c, section);
}
return mapSections.values();
}
// Create an inner class
public class Sections{
public Section__c section {get; set;}
public Question__c[] questions {get; set;}
public Map<Id, Answer__c> response {get; set;}
public Sections(Section__c sec){
section = sec;
questions = new Question__c[]{};
response = new Map<Id, Answer__c>();
}
}
}
Visualforce
<apex:page Controller="QuestionsList" >
<apex:pageBlock title="Questions List" >
<apex:repeat value="{!Sections}" var="sec" >
<!-- display section -->
<apex:outputText value="{!sec.section.Name}" />
<apex:repeat value="{!sec.questions}" var="q" >
<!-- display questions -->
<apex:outputText value="{!q.Name}" />
<!-- display answer -->
<apex:outputText value="{!sec.response[q.Id].Name}" />
</apex:repeat>
</apex:repeat>
</apex:pageBlock>
</apex:page>
Thanks a ton for writing the code and explaining it clearly.
I have 1 issue though, some of my response may be null that means no response record for a particular question.
That is why it may be giving me the error as
"Map key a02d0000006afMBAAY not found in map".
Is there a way we can check that so the response is output as blank if there is no record for it.
Thanks again
Arpi
Apex code:
public with sharing class QuestionsList {
// Creates section List
public List<Sections> getSections(){
Map<Id, Sections> mapSections = new Map<Id, Sections>();
// Add Section Records
for (Section__c sec : [SELECT Id, Name FROM Section__c]){
mapSections.put(sec.Id, new Sections(sec));
}
// Add Question Records
for (Question__c ques : [SELECT Id, Name, Section__c FROM Question__c]){
// Add question records to section
Sections section = mapSections.get(ques.Section__c);
section.questions.add(ques);
// Here i added all the question Ids in to the map
section.response.put(ques.Id, new Answer__c());
mapSections.put(ques.Section__c, section);
}
// Add Answer Records
Map<Id, Answer__c> mapAnswer = new Map<Id, Answer__c>();
for (Answer__c ans : [SELECT Id,Name, Question__c, Question__r.Section__c FROM Answer__c]){
Sections section = mapSections.get(ans.Question__r.Section__c);
section.response.put(ans.Question__c, ans);
mapSections.put(ans.Question__r.Section__c, section);
}
return mapSections.values();
}
// Create an inner class
public class Sections{
public Section__c section {get; set;}
public Question__c[] questions {get; set;}
public Map<Id, Answer__c> response {get; set;}
public Sections(Section__c sec){
section = sec;
questions = new Question__c[]{};
response = new Map<Id, Answer__c>();
}
}
}
Visualforce
<apex:page Controller="QuestionsList" >
<apex:pageBlock title="Questions List" >
<apex:repeat value="{!Sections}" var="sec" >
<!-- display section -->
<apex:outputText value="{!sec.section.Name}" />
<apex:repeat value="{!sec.questions}" var="q" >
<!-- display questions -->
<apex:outputText value="{!q.Name}" />
<!-- display answer -->
<apex:outputText value="{!sec.response[q.Id].Name}"
rendered="{!IF(NOT(ISNULL(sec.response[q.Id])),'true','false')}" />
</apex:repeat>
</apex:repeat>
</apex:pageBlock>
</apex:page>
Hope, this will work for you.
great soultion ,can anyone tell how to maintain the order of section and questions.The map is unordered so please guide.
Thanks
mba