0

I have a repeat block that loops over a List<String> and outputs them to an HTML table.

Underneath that is the actionFunction declaration followed by an HTML button which when clicked calls the actionFunction.

The controller function simply concats to the end of a public string property which I then debug out.

When I first click the button the output is "set in constr; testParamVal;" which is expected however when I click the button the second time the output is the same where as I was expecting "set in constr; testParamVal; testParamVal;".

Upon lots of trial and error I found that if I removed the HTML table tags from around the repeat block this worked as expected.

Is this a bug or am I missing something?? Thanks!

Working

VF Page:

<apex:page controller="TestPage2_Ctrl">

    <apex:form >
        <apex:pageBlock >
            <apex:pageBlockSection title="actionFunction Test" columns="1" id="testPBS">

                <!-- <table> -->
                    <apex:repeat value="{!TestList}" var="strVal">
                        <!-- <tr>
                            <td>{!strVal}</td>
                        </tr> -->
                        {!strVal}
                    </apex:repeat>
                <!-- </table> -->

                <apex:actionFunction name="testPostback" action="{!TestPostback}" rerender="testPBS" />

                <button type="submit" onclick="testPostback(); return false;">
                    Test postback
                </button>

            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>

</apex:page>

Controller:

public class TestPage2_Ctrl {

    public String TestVal {get; set;}
    public List<String> TestList {get; set;}

    public TestPage2_Ctrl() {
        TestList = new List<String>();
        TestList.add('testVal 1');
        TestList.add('testVal 2');
        TestList.add('testVal 3');

        TestVal = 'set in constr; ';
    }

    public void TestPostback() {
        TestVal += 'testParamVal; ';
        system.debug('TestVal post add: ' + TestVal); // expect "set in constr; testParamVal; testParamVal;" on second button click
    }

}

Not Working

VF Page:

<apex:page controller="TestPage2_Ctrl">

    <apex:form >
        <apex:pageBlock >
            <apex:pageBlockSection title="actionFunction Test" columns="1" id="testPBS">

                <table>
                    <apex:repeat value="{!TestList}" var="strVal">
                        <tr>
                            <td>{!strVal}</td>
                        </tr>
                        {!strVal}
                    </apex:repeat>
                </table>

                <apex:actionFunction name="testPostback" action="{!TestPostback}" rerender="testPBS" />

                <button type="submit" onclick="testPostback(); return false;">
                    Test postback
                </button>

            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>

</apex:page>

Controller:

Same as above

EDIT

VF API version is 28.0 Apex API version is also 28.0. On a Winter 15 dev sandbox

  • 2
    HI I think Repeat control creates its own table and tbody tag. In this case if table tag is used outside repeat control then table tag outside repeat control wont find next tr tag which is error acc to HTML – DKSalesforce Lerner Feb 11 '15 at 11:04
1

Problem: here repeat control has it own table tag.

doing this

<table>     //outside repeat table tag
   <table> // inside repeat table tag

   </table>
</table>

solution: As I can see you are trying to create html table tag code through repeat control so instead you can do this:

In visual force page:

<apex:outputtext escape="true" value="{!a_variable_in_controller}" />

here escape="true" means you are allowed for html tags coming form controller.

In controller:

public String a_variable_in_controller {get;set;}

In constructor of same controller:
a_variable_in_controller='<table>';
for(dt a:TestList){  // dt is a datatype of each TestList record
   a_variable_in_controller+='<tr><td>'+strVal+'</td></tr>';
}
a_variable_in_controller+='</table>';

I think this might help you Please Ignore syntax error if any :)

  • Thanks @DK. Personally I would say that the controller shouldn't contain HTML where possible but your solution could be useful in some situations! – Force Hero Feb 11 '15 at 11:26
  • Your previous comment got me thinking on the right line in order to solve the problem as per my answer - thanks very much! :) – Force Hero Feb 11 '15 at 11:26
  • My pleasure @Force Hero – DKSalesforce Lerner Feb 11 '15 at 11:30
1

Thanks @DKSalesforce Lerner! Because the <apex:repeat> was a direct child of a <apex:pageBlockSection> it generates a load of its own table HTML.

I put the <apex:repeat> inside a <apex:outputPanel layout="block"> which stopped it from generating its own HTML which in turn allowed the view state to be passed back forth correctly!

I should have read the docs :)

http://www.salesforce.com/us/developer/docs/pages/Content/pages_compref_repeat.htm

Note that if used within an <apex:pageBlockSection> or <apex:panelGrid> component, all content generated by a child component is placed in a single <apex:pageBlockSection> or <apex:panelGrid> cell.

1

Here its true that repeat control internally creates its own table tag when its converted into HTML

hence solution would be not to use repeat but some thing similar to repeat. apex datatable control internally handle all html tags you dont have to write any code for this as salesforce handle it for you.

solution:

<apex:dataTable value="{!TestList}" var="strVal" id="theTable" rowClasses="odd,even" styleClass="tableClass">
        <apex:column>
            <apex:outputText value="strVal"/>
        </apex:column>
</apex:dataTable>

I hope this might help you. :) Happy coding.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.