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
ArpiArpi 

<apex:repeat to iterate 2 objects alternatively

Hello,

 

I have a 2 lists which i want to display alternatively.

My code is 

 

<apex:repeat value="{!questionsList}" var="section">
<apex:variable var="rlists" value="{!section.rlistss}"/>
<apex:variable var="i" value="{!0}"/>
<apex:repeat value="{!section.qlistss}" var="qlist">
<apex:outputField value="{!qlist.Question_Label__c}" />
<apex:outputField value="{!rlists[i].Response__c}" /> <!--This doesnt workhow to iterate this also after each question display 1 response-->
<br> </br>

</apex:repeat>

 

 

Thanks

Best Answer chosen by Admin (Salesforce Developers) 
AdrianCCAdrianCC

Hello @Arpi,

 

I suggest using a wrapper class to put togheter pairs of question-response. This way you'll only need one repeat in the VF.

 

So in the controller you'll have smth like:

public class Wrapper {
	public Question__c question  	{get; set;}
	public Response__c response 	{get; set;}

	public Wrapper(Question__c question, Response__c response) {
		this.question = question;
		this.response = response;
	}
}

public List<Wrapper> wrapperList 	{get; set;}

//in teh controller's constructor initialize the wrapperList

 And in the VF page:

<apex:repeat value="{!wrapperList}" var="wrapper">
	<apex:outputField value="{!wrapper.question.Question_Label__c}" />
	<apex:outputField value="{!wrapper.response.Response__c}" /> 
</apex:repeat>

 

Does this solve your problem?

 

Thank you,

Adrian

 

 

All Answers

AdrianCCAdrianCC

Hello @Arpi,

 

I suggest using a wrapper class to put togheter pairs of question-response. This way you'll only need one repeat in the VF.

 

So in the controller you'll have smth like:

public class Wrapper {
	public Question__c question  	{get; set;}
	public Response__c response 	{get; set;}

	public Wrapper(Question__c question, Response__c response) {
		this.question = question;
		this.response = response;
	}
}

public List<Wrapper> wrapperList 	{get; set;}

//in teh controller's constructor initialize the wrapperList

 And in the VF page:

<apex:repeat value="{!wrapperList}" var="wrapper">
	<apex:outputField value="{!wrapper.question.Question_Label__c}" />
	<apex:outputField value="{!wrapper.response.Response__c}" /> 
</apex:repeat>

 

Does this solve your problem?

 

Thank you,

Adrian

 

 

This was selected as the best answer
newbiembanewbiemba

Hey,

 

I am having the same problem but I have one more level to it ,1 section for a user can have mutilple questions and each question has response.

So if i iterate trough the sections, I have to store that too.

So 1 section has a list of questions and answers something like this so please guide.

 

 

public class Wrapper {
	public Question__c question[]  	{get; set;}
	public Response__c response[] 	{get; set;}

	public Wrapper(Question__c question, Response__c response) {
		this.question = question;
		this.response = response;
	}
}

public List<Wrapper> wrapperList 	{get; set;}

 

AdrianCCAdrianCC

Same design.

 

You use a wrapper class for each level. 

At the bottom of the hierarchy you have Response. Then Question, which can have multiple Responses. And above the Section which has a list of Questions...

public class Section {
	public String name 				 	{get; set;}
	public List<Question> qeustionList  {get; set;}
	...
}


public class Question {
	public String name 				 	{get; set;}
	public List<Response> responseList  {get; set;}
	...
}

public class Response {
	public String name 					{get; set;}
	public String text					{get; set;}
	...
}

public List<Section> sectionList      	{get; set;}


<apex:repeat value="{!sectionList}" var="section" >
	<apex:outputField value="{!section.Name}" />
	<apex:repeat value="{!section.qeustionList}" var="question" >
		<apex:outputField value="{!question.Name}" />
		<apex:repeat value="{!question.responseList}" var="response" >
			<apex:outputField value="{!response.Name}" />
		</apex:repeat> 
	</apex:repeat> 
</apex:repeat>

 I don't know exactly how you want the page to look, but I suggest using a tabpanel and tabs to make it look pretty :)

 

Happy inception,

Adrian

 

newbiembanewbiemba

Hello,

 

Thanks Adrian for the reply but I some issues.

I have 1 question and 1 response so i am not using response class.

Also my response can be null but i still want to display the question and also maintain the order for each section and question.It gives me first errors.

1)in vf 

Could not resolve the entity from <apex:outputField> value binding '{!section.Name}'. <apex:outputField> can only be used with SObject fields

2)If i remove everything from vf than it gives in apex :

List index out of bounds: 0

 

 

or sometime too many sql queries.

 

Below is the code

 

public class Questionnaire
{
public List<Section__c > sectionsLists{ get; set; }
public List<Question__c> questionsLists { get; set; }

public class Section
{
public String name {get; set;}
public List<Question> questionList {get; set;}


}
public class Question
{
public String name {get; set;}
public List<Response> responseList {get; set;} //not using
public String responsename {get; set;}
}

public class Response
{//not using
public String name {get; set;}
public String text {get; set;}
}
public List<Section> sectionList {get; set;}

public void sectionDisplay()
{
sectionList = new List<Section>();

sectionsLists = [Select Id,Section_label__c,Order_No__c from Section_c order by Order_No__c];
for(Section__c sec: sectionsLists )
{
Section s=new Section();
s.name=sec.Section_label__c;
s.questionList =new List<Question>();
questionsLists = [SELECT Id,Section_Question__r.id,Question_Label__c,Question_Order_No__c FROM Question__c where Section_Question__r.id=:sec.id order by Question_Order_No__c];

for(Question_c quest: questionsLists )
{
Response__c[] reponseObject=[Select id,Response__c,Question__c,Account_to_Response__c from Response__c where Question__c=:quest.id] ;
Question q=new Question();
q.name=quest.Question_Label__c;
if(reponseObject==null)
{
q.responsename='';
}
else
{
q.responsename=reponseObject[0].Response__c;
}

s.questionList.add(q);
}
sectionList.add(s);
}



}
}
}//end main class


<apex:page standardController="section_c" extensions="Questionnaire" recordSetVar="site" action={!sectionDisplay}" id="thepage">
<apex:pageBlockSection id="sectionBlock" title="{!templateName}" columns="1" >
<apex:variable var="snum" value="{!1}"/>

<apex:repeat value="{!sectionList}" var="section" >
<apex:outputField value="{!section.Name}" />
<apex:repeat value="{!section.questionList}" var="question" >
<apex:outputField value="{!question.Name}" />

<apex:outputField value="{!question.responsename}" />

</apex:repeat>
</apex:repeat>

</apex:pageBlockSection>
<apex:page>

 

Please help I dont know what I am missing.

AdrianCCAdrianCC

Are you sure you are not getting any other errors?! I see you're using the class as an extension, so you need to have a constructor that uses the standardcontroller...

 

1. you cannot use apex:outputField element for variables that are not sObject fields...(hence the 'field' in the outputField). Try to use apex:outputText 

2. I don't understand what you mean by "If i remove everything from vf" but that error happens because you're hardcoding 0 when getting an element from a list( see line 52, q.responsename=reponseObject[0].Response__c;). The list doesn't have any elements so you get the error... Use System.debug to see the values of the lists and check for null

 

Other stuff:

- create constructors for those wrapper classes

- don't create soqls inside of for structures... you can reach the governor limits very very fast. Use Maps, Sets etc to bulkify your code

- for questions that don't have any response you can create a blank response wrapper; or you can show a certain message using conditional outputpanels (with rendered="{!IF(response=null, 'no response', response)}"

 

Thanks,

Adrian

Ravi DesrajRavi Desraj

newbiemba, Did you solve your proble?