3

I want to know how to hide a row using jQuery (I have jQuery set up in my code already). Let's say I have an object called Entry, and I have several records like E-0001, E-0002, E-0003 etc. I have a data table that lists those records as such:

Entries | Date

E-0001 | 12/1/2012

E-0002 | 5/2/2011

E-0003 | 7/2/2011

I would like to add a button next to each record that will hide the record and the row:

Entries | Date

(-) E-0001 | 12/1/2012

(-) E-0002 | 5/2/2011

(-) E-0003 | 7/2/2011

So if I pressed the (-) next to 'E-0001', it will hide that record so the result would be

Entries | Date

(-) E-0002 | 5/2/2011

(-) E-0003 | 7/2/2011

And even after a page reload, that row should still be appear to be gone (but the record itself not permanently deleted!). ALSO: it should only be hidden to the user, NOT globally. Thank you!

Edit: Visualforce code

<apex:page showheader="true" standardController="Entry__c" recordsetVar="entries" sidebar="false" extensions="entryExtension" >
<head>
    <apex:includeScript value="{!URLFOR($Resource.jquery, 'jquery-ui-1.9.0.custom/js/jquery-1.8.2.min.js')}"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery, 'jquery-ui-1.9.0.custom/js/jquery-ui-1.9.0.custom.min.js')}"/>
    <apex:stylesheet value="{!URLFOR($Resource.jquery, 'jquery-ui-1.9.0.custom/css/pepper-grinder/jquery-ui-1.9.0.custom.css')}"/>

<script>
   $j = jQuery.noConflict();
   function hideRow(){


   }
</script>
</head>    
<body>
              <apex:pageBlock title="View Recent Entries" mode="edit">  
                <apex:pageBlockSection title="Entry Information" columns="2">  
                    <apex:dataTable value="{!entries}" var="e" cellpadding="4" border="1" width="475">

                    <apex:column >
                    (-)
                    </apex:column>

                    <apex:column >
                    <apex:facet name="header"><b>Name</b></apex:facet>
                        {!e.name}
                    </apex:column>

                    <apex:column >
                        <apex:facet name="header"><b>Level One</b></apex:facet>
                        {!e.Join__r.Level_One__r.name}
                    </apex:column>

                    <apex:column >
                        <apex:facet name="header"><b>Level Two</b></apex:facet>
                        {!e.Join__r.Level_Two__r.name} 
                    </apex:column>

                    <apex:column >
                        <apex:facet name="header"><b>Date</b></apex:facet>
                        {!e.Date__c}
                    </apex:column>

                    <apex:column >
                        <apex:facet name="header"><b>Hours</b></apex:facet>
                        {!e.Hours__c}
                    </apex:column>

                    </apex:dataTable>
           </apex:pageblocksection>
           </apex:pageblock>

</body>
</apex:page>
4
  • 1
    Could you post some of your code? It's tricky to give a specific answer without seeing how you're producing your table.
    – metadaddy
    Nov 8 '12 at 19:03
  • jQuery questions would be better directed to Stack Overflow stackoverflow.com/questions/tagged/jquery Nov 8 '12 at 19:15
  • @metadaddy I have included it in my original post.
    – sharrie
    Nov 8 '12 at 19:43
  • @Ralph I will look there, thank you, but part of my problem is how to make jQuery interact with my VF code. I've looked at a few articles on jQuery + VF as well as other people's problems, but they did not help me very much especially since I could not find more in-depth stuff on google. Or maybe I just suck at searching :p I'll keep looking.
    – sharrie
    Nov 8 '12 at 19:45
3

There are two dimensions to this question, one is the hiding on the UI and the other persisting the hiding (even after a refresh)

To hide on the UI, you can use the jQuery.hide() function, which is trivial.

To persist the hiding, you will need to proxy it via an actionFunction (equally you could use JS-Remoting via Jquery, but I've chosen actionFunction for the purposes of this illustration) to the controller class, so it can process the Id and possibly, set a field on the Account to hide it in further loads. Now if you want a different behaviour per use (i.e. hidden only for the user who has hidden it, then you will possibly need to create another object, where you will store a user's 'hide' preferences, a user Id - hidden id mapping of sorts)

Here's my illustration using Accounts, where I've implemented the hide behaviour using both jQuery and proxying through actionFunction. You can bolt on the behaviour to persist the hiding in the controller action method which is invoked when Hide is clicked.

Visualforce Page :

<apex:page controller="AccountListController">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>

<script>

jQuery.noConflict();

function proxyHideItem(accId){
//uncomment this to hide via jquery, currently hiding via actionFunction
//jquery selector using the class, which is accountId for each row
//jQuery("."+accId).hide();

hideItem(accId);

}
</script>

<apex:form> //action function proxies to controller,which sets visible false

<apex:actionFunction name="hideItem" action="{!hideAccount}" reRender="thePageBlock">
<apex:param id="paramId" name="accToHide" value="" />
</apex:actionFunction>

<apex:pageBlock id="thePageBlock">
<apex:pageMessages/>

<apex:pageBlockSection>
<apex:dataTable value="{!accountList}" var="acc">

//notice how the styleClass is the accountId, to select using Jquery
<apex:column   styleClass="{!acc.accId}"  rendered="{!acc.Visible}">
<apex:facet name="header"><b>Hide</b></apex:facet>
<apex:outputPanel onclick="proxyHideItem('{!acc.accId}');" >Hide</apex:outputPanel> 

</apex:column>

<apex:column   styleClass="{!acc.accId}"  rendered="{!acc.Visible}">
<apex:facet name="header"><b>Id</b></apex:facet>
{!acc.accId}
</apex:column>

<apex:column   styleClass="{!acc.accId}"  rendered="{!acc.Visible}">
<apex:facet name="header"><b>Name</b></apex:facet>
{!acc.accName}
</apex:column>

</apex:dataTable>

</apex:pageBlockSection>

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

</apex:page>

Controller :

public class AccountListController{

Map<Id, AccountWrapper> accMap = new Map<Id, AccountWrapper>();

public List<AccountWrapper> getAccountList(){
    if (accMap == null || accMap.isEmpty()){
        for(Account acc : [Select Id, Name from Account LIMIT 25]){
            accMap.put(acc.Id, new AccountWrapper(acc));
        } 
    }
    return accMap.Values();
}

//this method is invoked via the action function
public PageReference hideAccount(){

Id accToHide = (Id)ApexPages.currentPage().getParameters().get('accToHide');
System.debug('**************************** Hiding ' + accToHide);
if(accToHide != null)
accMap.get(accToHide).visible = false;

//here is where you can bolt on behaviour to store the account hide event
//either a field on account if hide is global for all users, or a dedicated
//hide object, if the hiding is user specific
return null;
}

//wrapper class to hold the Visible variable, which controls visibility
public class AccountWrapper{

public Account acct {get; set;}

public Id accId {get { return acct.Id ; }}

public String accName {get { return acct.Name ;} }

public boolean visible { get; set; }

public AccountWrapper(Account acc){

this.visible = true;
this.acct = acc;

}
}
}
2
  • Thank you for this. I do want it to be user-specific. Can you explain the "a user Id - hidden id mapping of sorts" to me? I'm still a beginner with jQuery and Salesforce, so this will take a bit of time for me to go through. I'll report back here when I can!
    – sharrie
    Nov 8 '12 at 21:32
  • I'll let you digest that, before elaborating any further :) There are a few options, Edit to follow... Nov 8 '12 at 22:03
1

First, you want to add the attribute rowClasses to your apex:datatable, so that you have something to find in the hierarchy when you click the link.

 <apex:dataTable value="{!entries}" var="e" cellpadding="4" border="1" width="475" rowClass="dataTableRow">

Next, associate a jquery click action to the icon:

<apex:column>       
   <a class="minus-element">-</a>
</apex:column

And the jQuery

$(function(){
   $('.minus-element').click(function(){
      $(this).parents().find('.dataTableRow').remove();
   });
});

Use Firebug / webkit developer tools and play with breakpoints to determine if you have correctly associated the classes and that they are able to find each other

2
  • I tried this and it removed all rows except the labels. I modified your jQuery a bit to this $j(function(){ $j('.minus-element').click(function(){ $j(this).parents('.dataTableRow').remove(); }); }); which worked in removing individual rows, yay!, partially solved. Thank you very much =) But would you know of anyway to keep the rows removed/hidden even after a page reload?
    – sharrie
    Nov 8 '12 at 20:50
  • You should than set some sort of attribute on the custom object type like Hidden__c or type Checkbox and than call a method from jquery to assign that value on the record using either actionFunction or @RemoteAction to asynchronously pass the record id and hide it. Nov 8 '12 at 20:56
1

I have tried something without Jquery just in case you are looking for Apexy way of doing this

DRAWBACK : You have to create a field called hidden_value in your object. for demo I used Account object, and created a field just for achieving this without using jquery and doing the APEX Way.

Page:

<apex:page showheader="true" standardController="account" recordsetVar="entries" sidebar="false" extensions="entryExtension" >
<head>
    <apex:includeScript value="{!URLFOR($Resource.jquery, 'jquery-ui-1.9.0.custom/js/jquery-1.8.2.min.js')}"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery, 'jquery-ui-1.9.0.custom/js/jquery-ui-1.9.0.custom.min.js')}"/>
    <apex:stylesheet value="{!URLFOR($Resource.jquery, 'jquery-ui-1.9.0.custom/css/pepper-grinder/jquery-ui-1.9.0.custom.css')}"/>

<script>
   $j = jQuery.noConflict();
   function hideRow(){


   }
</script>
</head>    
<body>
<apex:form id="theForm">
              <apex:pageBlock title="View Recent Entries" mode="edit">  
                <apex:pageBlockSection title="Entry Information" columns="2">  
                    <apex:dataTable value="{!account_val}" var="e" cellpadding="4" border="1" width="475">

                    <apex:column >
                    <apex:commandlink value="(-)" action="{!removerow}">
                    <apex:param name="strattoupdate" assignTo="{!hidden_Id}" value="{!e.Id}"/>
                    </apex:commandlink>
                    </apex:column>

                    <apex:column >
                    <apex:facet name="header"><b>Name</b></apex:facet>
                        <apex:outputlink value="/{!e.Id}" target="_blank"> {!e.name}</apex:outputlink>
                    </apex:column>


                    </apex:dataTable>
           </apex:pageblocksection>
           </apex:pageblock>
</apex:form>
</body>
</apex:page>

controller :

public with sharing class entryExtension {
    public string hidden_Id{get;set;}
    public list<account> account_val{get;set;}
    public entryExtension(ApexPages.StandardSetController controller) {
    account_val =[select id,name from account where hidden_field__c =: FALSE limit 5];
    }
    public pagereference removerow(){
    system.debug('%%%%' + hidden_id);
    account acc = new account(id= hidden_id,hidden_field__c = true);
    database.saveresult sr = database.update(acc);
    if(sr.Issuccess()){
    system.debug('### Acc'+ acc);}
    pagereference page = new pagereference ('/apex/hide_jq');
    page.setredirect(true);
    return page;
    }
}
3
  • Thank you I will also try this out. Should that hidden_value field be a checkbox-type for true & false?
    – sharrie
    Nov 8 '12 at 21:52
  • Yes it is a checkbox on the account.
    – Rao
    Nov 8 '12 at 22:03
  • @sharrie did this approach help?
    – Rao
    Nov 8 '12 at 23:03
0

Assuming that you know the jQuery that you are going to use - you will be attaching a click event which hides the tr element perhaps - then your problem here is to identify from the html produced by visual force which elements you need to capture in your jQuery selector.

To do this, in the apex:column corresponding to your minus icon add the attribute styleclass="hideicon"

This will then be rendered with that style and you can pick it up in the jQuery selector using .hideicon

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.