0

Page displays:

String userinput (from apex:inputText) only in last row of apex:repeat. It doesn't allow to check is userInput=question.Correct_answer

Image:

Link to image

Visualforce page:

<table class="examTable">
            <apex:variable value="{!1}" var="index"/>
            <apex:repeat var="question" value="{!questions}">
                <tr style="display: {!IF(passedExam.Question_Number__c==index,'table-row','none' )}">
                    <td styleClass="question" width="50%">{!question.Question__c} {!index}</td>
                    <td width="10%">{!question.AnswerA__c}</td>
                    <td width="10%">{!question.AnswerB__c}</td>
                    <td width="10%">{!question.AnswerC__c}</td>
                    <td width="10%">{!question.AnswerD__c}</td>
                    <td width="10%">
                        <apex:inputText label="your answer" value="{!userInput}"/>
                        <apex:outputPanel><a href="javascript:if (window.confirm('Are you sure?')) checkAnswer('{!question.Id}');">Check and Next »</a>
                        </apex:outputPanel>
                    </td>
                </tr>
                <apex:variable var="index" value="{!index+1}"/>
            </apex:repeat>
        </table>
    <apex:actionFunction action="{!checkAnswer}" name="checkAnswer" >
        <apex:param name="id" value="" assignTo="{!currentQuestion}"/>
    </apex:actionFunction>

Controller:

public String userInput { get; set; }
public String currentQuestion {get;set;}

public void checkAnswer() {
    if (passedExam.Question_Number__c < questions.size()) {
        if (currentQuestion == null) {
            return;
        }

        for (Question__c question : questions)
            if (question.Id == currentQuestion) {
                if (question.CorrectAnswer__c == userInput) {
                    passedExam.Count_correct_answers__c = passedExam.Count_correct_answers__c + 1;
                }
            }
        passedExam.Question_Number__c = passedExam.Question_Number__c + 1;
        upsert passedExam;
    } else if (passedExam.Question_Number__c == questions.size()) {
        passedExam.Count_correct_answers__c = passedExam.Count_correct_answers__c + 1;
        passed = true;
        upsert passedExam;
    }
}
2
  • Please provide more details. When does this error show, when you click a button or when the page loads?
    – Eduard
    Commented Jul 27, 2018 at 9:18
  • when im opening page i see question #1. when i click "checkAnswer" controller check if userInput =question1. then i see question#2, input and controller check again. it should be. but in real life controller get userInput String value only on last question, last apex:repeat row. Thank you!!!
    – Ivan S.
    Commented Jul 27, 2018 at 9:21

1 Answer 1

1

Well a lot of stuff is going here - you need reconsider the whole design. Search for Visualforce and Apex best practices. For example, <tr style="display: {!IF(passedExam.Question_Number__c==index,'table-row','none' )}"> is not good since other rows a rendered in DOM (yeah, they are not visible on the page). But your main intent, I assume, is not to have a row in the table if it does not satisfy the condition at all. That's just one example out of many...

Now to the problem. Your issue happens because you pass only currentQuestion when making a call to checkAnswer. That makes the controller use the value from the last row of your table as userInput. An I guess, when you display row 1 in your table the last (and other rows) will be hidden, and the latest value assigned to userInput would be from the last row in your table.

What you should do is ensure both currentQuestion and userInput post values your assigned when you call checkAnswer:

    ....
    <apex:inputText label="your answer" onchange="assignInput(this.value);"/>
    <apex:outputPanel><a href="javascript:if (window.confirm('Are you sure?')) checkAnswer('{!question.Id}');">Check and Next »</a>

    ...

    <apex:inputHidden styleClass="userInputHIdden" id="userInputHIdden" value="{!userInput}"/>
    <script>
      function assignInput(val)
      { 
        // Use querySelectorAll instead of getElementById so that no need to use {!Compoent...} to get the actual Id of the element. For the sake of this example
        document.querySelectorAll(".userInputHIdden")[0].value = val;
      }
   </script>
    ...

You must log in to answer this question.

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