1

Is it possible to put logic within apex:repeat in VisualForce page? I have code as shown below but instead of executing logic of array split and then displaying table contents, visual force page is displaying entire string prop as defined below and then the table row

<table>
    <tr>
        <td>Head 1</td>
        <td>Head 2</td>
        <td>Head 3</td>
        <td>Head 4</td>
    </tr>    
    <apex:repeat value="{!queries}" var="query">
     string[] prop = ({!query.MyField}).Split('\n');
     for (string s :prop)
     {
        if (s.Contains('='))
        {
            <tr>    
               <td>{!query.Field1}</td>
               <td>{s[0]}</td>
               <td>{!query.Field2}</td>
               <td>{s[1]}</td>
           </tr>
      }
     }
    </apex:repeat>
</table>

I can't modify controller since it is managed and I have no access to source code.

2
  • I don't believe you can do it that way. You should rather create a wrapper class within your controller, populate with the contents that you want and then simply display that in the table. https://developer.salesforce.com/page/Wrapper_Class – Aayush K Dec 1 '15 at 16:43
  • yes, updating controller is an option but would like to avoid it and curious to know if VF page has that capability – user569925 Dec 1 '15 at 16:46
4

While you can have some logic within repeat tags, you can't include literal Apex Code. You could, however, achieve this with either JavaScript (albeit clumsily), or by rendering this data with a wrapper class and some helper functions.

You'll see you have to use "formula-like" constructs, so it has some limitations (e.g. you can't get the a string into an array using pure Visualforce). A close approximation of what you could write might look like this:

<apex:repeat value="{!queries}" var="query">
    <apex:repeat value="{!query.MySplitField}" var="splitPart">
        <apex:outputText rendered="{!CONTAINS(splitPart,'=')}">
            <tr>
                <td>
                    {!query.Field1}
                </td>
                <td>
                    {!LEFT(splitPart, FIND(splitPart,'='))}
                </td>
                <td>
                    {!query.Field2}
                </td>
                <td>
                    {!RIGHT(splitPart, FIND(splitPart,'='))}
                </td>
            </tr>
        </apex:outputText>
    </apex:repeat>
</apex:repeat>

However, you'll have to "wrap" your records into a wrapper class:

public class Wrapper {
    MySObject record;
    Wrapper(MySObject record) {
        this.record = record;
    }
    public String[] getMySplitField() {
        if(record.MyField != null) {
            return record.MyField.split('\n');
        }
        return new String[0];
    }
    public String getField1() {
        return record.Field1;
    }
    public String getField2() {
        return record.Field2;
    }
}

You add records to the wrapper like so:

public Wrapper[] getQueries() {
    Wrapper[] results = new Wrapper[0];
    for(MySObject record:[SELECT MyField, Field1, Field2 FROM MySObject]) {
        results.add(new Wrapper(record));
    }
    return results;
}

As JavaScript, it'd probably be easier to just make a remote call for the data and then render it (perhaps by using jQuery). You could probably, however, expose the "queries" data simply by doing the following:

<script>
    var queries = {!queries};
    $.each(queries, function(i,v) {
        $.each(v.MyField.split("\n"), function(i2,v2) {
            if(v2.match(/=/)) {
                // Render the desired elements
            });
        });
</script>

This might get tricky if you're trying to use reRenders and so on, but is certainly possible.

4
  • I can't modify controller since it is managed and I have no access to controller. I will try JavaScript – user569925 Dec 1 '15 at 18:06
  • 1
    You might be able to write an extension, if the controller were global. – sfdcfox Dec 1 '15 at 18:08
  • does that controller need to be 'virtual' too? It is global. – user569925 Dec 1 '15 at 19:43
  • @user569925 No, it doesn't need to be virtual, only global. Simply set the other controller as the primary controller (apex:page controller="ns.classname"), then accept it into your constructor (public myExtension(ns.className externalController)). – sfdcfox Dec 1 '15 at 19:49

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.