5

I have a Visualforce page that uses jQuery for various functions. One thing I'm trying to do is using the jQuery.isEmpty function on an apex:repeat value.

Relevant Visualforce code:

 <apex:pageBlockSection id="existingOpps" columns="3" title="Existing opportunities" collapsible="false">
            <apex:repeat id="oppRepeatValue" value="{!existingOpps}" var="o">
                <apex:outputLabel id="OpportunityText" value="{!o.forOpportunityName__c}"></apex:outputLabel>
                <apex:outputLabel value="{!o.forVisitReportName__c}"></apex:outputLabel>
                <apex:outputLabel value="{!o.forVisitReportDate__c}"></apex:outputLabel>
            </apex:repeat>
        </apex:pageBlockSection>

The Visualforce code is translated into HTML code that looks like this:

<table class="detailList" border="0" cellpadding="0" cellspacing="0"><tr><th class="labelCol vfLabelColTextWrap  first  last " scope="row"><label for="j_id0:theForm:pb:existingParticipants:partRepeatValue:0:participantText">Type</label></th><td class="dataCol  first  last "><span id="j_id0:theForm:pb:existingParticipants:partRepeatValue:0:participantText" style="label">Contact</span></td><td class="dataCol  first  last " colSpan="2"><label id="j_id0:theForm:pb:existingParticipants:partRepeatValue:0:participantname" style="label"></table>

So, my question is, how can I use jQuery (or just plain JavaScript techniques) to check whether that generated table is empty or not? What I've tried so far is this JavaScript function.

 function checkValidOnExit(){
   var pso = document.getElementById("{!$Component.theForm.pb.existingParticipants.participantname}");
   var oso = document.getElementById("{!$Component.theForm.pb.existingOpps}");
 if(j$.isEmptyObject(pso) || j$.isEmptyObject(oso))

   window.alert("error");

   }

I.e by trying to check whether the HTML object/container is empty. If so, alert the user through the page being viewed (ApexPages.Message, etc.). What is the best way to handle this? Pure JavaScript function or use a controller method?

4

If your goal is simply to notify users that there are no existing opportunities, then you can do that without Javascript and without modifications to your existing controller/extension by making use of the rendered attribute.

<apex:pageBlockSection id="existingOpps" columns="3" title="Existing opportunities" collapsible="false">
    <!-- This pb section item only appears when there are no existing opps -->
    <apex:pageBlockSectionItem rendered="{!existingOpps.empty}">
        There are no existing Opportunities
    </apex:pageBlockSectionItem>
    <!-- Specifying rendered here makes the repeat only visible when existingOpps is *not* empty -->
    <!-- {!!existingOpps.empty} and {!NOT(existingOpps.empty)} are logically equivalent, but it's a lot harder to miss a 'NOT()' than it is to miss a '!!' -->
    <apex:repeat id="oppRepeatValue" value="{!existingOpps}" var="o" rendered="{!NOT(existingOpps.empty)}">
        <apex:outputLabel id="OpportunityText" value="{!o.forOpportunityName__c}"></apex:outputLabel>
        <apex:outputLabel value="{!o.forVisitReportName__c}"></apex:outputLabel>
        <apex:outputLabel value="{!o.forVisitReportDate__c}"></apex:outputLabel>
    </apex:repeat>
</apex:pageBlockSection>

+edit:

I'm not sure if you really need to specify the rendered attribute for an <apex:repeat> when it has no elements to iterate over. The <apex:repeat> itself may be generating some container element(s) (even if there is nothing to put inside of them), which could throw off the layout of your Visualforce page.

The safe way to go about this is to specify the rendered attribute.

3
  • 1
    You could also use the same rendered property elsewhere, such as to disable the save button. I might change {!!<empty_check>} to {!!NOT(<empty_check>)}. That double bang always seems too easy to miss or otherwise cause confusion. – Adrian Larson Mar 10 '17 at 15:27
  • 1
    @AdrianLarson That makes sense (though I think you meant to say {!NOT(<empty check>)}). Double bangs are very easy to gloss over. – Derek F Mar 10 '17 at 15:34
  • Ha. Case in point. – Adrian Larson Mar 10 '17 at 16:07
3

For the question in the title, you can just merge in the list itself and reference its empty property.

var isEmpty = {!existingOpps.empty};
if (isEmpty) {
    // do stuff
}

This approach would work equally well using a size check.

var isEmpty = {!existingOpps.size == 0};
if (isEmpty) {
    // do stuff
}

As for where is the best place to validate, I agree with others here that Javascript is not the best approach.

Here is one example straight from a project I'm working on that simply prevents you from performing the save action unless the collection has elements to save:

<apex:commandButton action="{!save}"
    value="Save ({!someCollection.size})"
    disabled="{!someCollection.empty}" />
2

I would validate these fields in your controller first and not do this using jQuery. You can easily add Apex.PageMessages or remove invalid data in your controller (your choice). You're simply adding overhead in the client page that doesn't need to be there. You could even filter these out in your Query if you wanted to.

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.