SOLUTION FOUND!!! The suggestion by Mohith Kumar to use actionFunction was the correct way to go. It just took a little research and better understanding of how actionFunction works to implement the solution. After some googling, I finally found a blog post (http://shivasoft.in/blog/salesforce/passing-parameter-in-actionfunction-in-visualforce/) that really helped me understand how to use actionFunction for my solution.
Here is the final code for the controller extension:
public with sharing class CanNewsChatterFeedExtension {
//declare class variables
public String feedItemId {get;set;}
public String likeId {get;set;}
public String commentToAdd {get;set;}
// Constructor. Needed to use as an extension.
public CanNewsChatterFeedExtension(CanNewsChatterFeedController custController) {}
//call via javascript and actionFunction. Class variables feedItemId and commentToAdd are set by passing params via actionFunction
public void addCommentToFeedItem(){
try{
FeedComment fcomment = new FeedComment();
fcomment.FeedItemId = feedItemId;
fcomment.CommentBody = commentToAdd; //String.escapeSingleQuotes(commentToAdd); <--prevents SOQL injection. Necessary?
insert fcomment;
}catch(Exception e){
System.debug(e.getMessage());
}
}
//call via javascript and actionFunction. Class variable feedItemId is set by passing params via actionFunction
public void addLikeToFeedItem(){
try{
ConnectApi.ChatterFeeds.likeFeedItem(null, this.feedItemId);
}catch(Exception e){
System.debug(e.getMessage());
}
}
//call via javascript and actionFunction. Class variable likeId is set by passing params via actionFunction
public void removeLikeFromFeedItem(){
try{
ConnectApi.ChatterFeeds.deleteLike(null, this.likeId);
}catch(Exception e){
System.debug(e.getMessage());
}
}
}
And the VF page final code:
<apex:page controller="CanNewsChatterFeedController" extensions="CanNewsChatterFeedExtension" id="feedcontroller" sidebar="false" showHeader="false" standardStylesheets="false" >
<script type="text/javascript">
var j$ = jQuery.noConflict();
/*called via JS onclick to pass in the itemId.
When addLike() is called it fires the actionFunction of the same name defined below,
which in turn passes the param to the apex class, sets the class variable and calls the defined apex method.
*/
function likeFeedItem(itemId){
addLike(itemId);
}
/*called via JS onclick to pass in the likeId.
When removeLike() is called it fires the actionFunction of the same name defined below,
which in turn passes the param to the apex class, sets the class variable and calls the defined apex method.
*/
function unLikeFeedItem(likeId){
removeLike(likeId);
}
//displays the commentBox for adding new comments
function showCommentBox(itemId){
j$('#comBox_'+itemId).show();
}
//clears the text in the commentBox onFocus
function clearCommentToAdd(itemId){
j$('#comIn_'+itemId).val('');
}
/*called via JS onclick to pass in the itemId.
When addComment() is called it fires the actionFunction of the same name defined below,
which in turn passes the params to the apex class, sets the class variables and calls the defined apex method.
*/
function addCommentToFeedItem(itemId){
var commentToAdd = j$('#comIn_'+itemId).val();
addComment(itemId, commentToAdd);
}
</script>
<style type="text/css">
.....
</style>
<div id="feed-display-div">
<apex:form >
<apex:pageMessages />
<apex:actionPoller action="{!refreshFeed}" rerender="feedRows" interval="60" />
<apex:outputPanel id="feedRows" >
<apex:repeat value="{!newsFeedForDisplay}" var="feedItemInfo" rows="10" rendered="{!NOT(ISNULL(newsFeedForDisplay))}">
<div class="row">
<div>
<div style="display:inline-block;vertical-align:top;">
<a href="/{!feedItemInfo.userId}">
<apex:image style="margin:4px" width="40" url="{!feedItemInfo.feedItem.photoUrl}"/>
</a>
</div>
<div style="display:inline-block;vertical-align:top;width:220px; color:#087bf5;">
<a href="/{!feedItemInfo.userId}">
<b>{!feedItemInfo.userName}</b>
</a><br/>
<apex:outputText style="color:#000000;" value="{!feedItemInfo.formattedText}" />
<apex:outputPanel layout="block" rendered="{!IF(feedItemInfo.linkUrl == null, false, true)}" >
<a href="{!feedItemInfo.linkUrl}">
<b>{!feedItemInfo.linkTitle}</b>
</a>
</apex:outputPanel>
<div class="comLikeDiv">
<a href="#" onclick="showCommentBox('{!feedItemInfo.feedItemId}')">Comment</a><span class="separatorDot">.</span>
<apex:outputPanel rendered="{!IF(feedItemInfo.isLikedByUser == true, false, true)}">
<span class="likeSpan" onclick="likeFeedItem('{!feedItemInfo.feedItemId}')">Like</span>
</apex:outputPanel>
<apex:outputPanel rendered="{!IF(feedItemInfo.isLikedByUser == false, false, true)}">
<span class="likeSpan" onclick="unLikeFeedItem('{!feedItemInfo.myLikeId}')">Unlike</span>
</apex:outputPanel>
<span class="separatorDot">.</span>
<apex:outputText styleClass="createdDate" value="{!feedItemInfo.relativeCreatedDate}" />
</div>
</div>
<apex:outputPanel layout="block" rendered="{!IF(feedItemInfo.contentDownloadUrl != null && feedItemInfo.imageUrl != null && feedItemInfo.hasImagePreview, true, false)}" >
<div style="left: 3em; width: 85%; padding: 2px; position: relative;">
<apex:image style="margin:4px" width="60" url="{!feedItemInfo.imageUrl}"/>
<div style="float:right;position:relative;padding:2px;width:65%;">
<a href="{!feedItemInfo.contentDownLoadUrl}">Download:<br />{!feedItemInfo.contentTitle }</a>
</div>
</div>
</apex:outputPanel>
</div>
<apex:outputPanel rendered="{!IF(feedItemInfo.likesMessage != '', true, false)}">
<div class="likeBox">
<div style="margin-left:4px;width:95%;">
<div style="display:inline-block;vertical-align:top;">
<apex:image value="{!$Resource.LikeThumb}" />
</div>
<div style="display:inline-block;width:80%;padding-top:2px;">
<apex:outputText style="margin-left:4px;" value="{!feedItemInfo.likesMessage}" />
</div>
</div>
</div>
</apex:outputPanel>
<apex:outputPanel rendered="{!IF(feedItemInfo.commentCount > 0, true, false)}">
<div class="commentBox">
<apex:repeat value="{!feedItemInfo.comments}" var="commentInfo">
<div class="commentBox-inner">
<div style="display:inline-block;vertical-align:top;">
<apex:image style="margin:4px" width="25" url="{!commentInfo.comment.user.photo.smallPhotoUrl}"/>
</div>
<div style="display:inline-block;vertical-align:top;width:80%">
<a href="/{!commentInfo.userId}">
<b>{!commentInfo.userName}</b>
</a>:
<apex:outputText value="{!commentInfo.formattedText}" />
<div class="createdDate">
<apex:outputText value="{!commentInfo.relativeCreatedDate}" />
</div>
</div>
<apex:outputPanel rendered="{!IF(commentInfo.imageUrl == null, false, true)}" >
<div style="padding-left:4px;display:inline-block;vertical-align:top;float:left;position:relative;width:95%" >
<apex:image style="padding:4px" width="60" url="{!commentInfo.imageUrl}"/>
<div style="float:right;position:relative;padding:2px;width:65%;">
<a href="{!commentInfo.contentDownLoadUrl}">Download:<br />{!commentInfo.contentTitle }</a>
</div>
</div>
<div style="clear: both;" />
</apex:outputPanel>
</div>
</apex:repeat>
</div>
</apex:outputPanel>
<div class="addComment" id="comBox_{!feedItemInfo.feedItemId}">
<input type="text" id="comIn_{!feedItemInfo.feedItemId}" style="border:1px solid #AAAAAA;" value="Add a comment..." onfocus="clearCommentToAdd('{!feedItemInfo.feedItemId}')" />
<apex:commandButton onclick="addCommentToFeedItem('{!feedItemInfo.feedItemId}')" value="Comment" rerender="feedRows" />
</div>
</div>
</apex:repeat>
<apex:actionFunction name="addLike" action="{!addLikeToFeedItem}" rerender="feedRows">
<apex:param name="theItemId" assignTo="{!feedItemId}" value="" />
</apex:actionFunction>
<apex:actionFunction name="removeLike" action="{!removeLikeFromFeedItem}" rerender="feedRows">
<apex:param name="theLikeId" assignTo="{!likeId}" value="" />
</apex:actionFunction>
<apex:actionFunction name="addComment" action="{!addCommentToFeedItem}" rerender="feedRows">
<apex:param name="theItemId" assignTo="{!feedItemId}" value="" />
<apex:param name="theComment" assignTo="{!commentToAdd}" value="" />
</apex:actionFunction>
</apex:outputPanel>
</apex:form>
</div>
Added a actionFunction which will reRender the page once the doSomething funciton is done executing. Try this out:
<script type="text/javascript">
function DoSomething(rcId,status){
try
{
var RCObj = new sforce.SObject("Child__c");
RCObj.id = rcId;
RCObj.Status__c = status;
sforce.connection.sessionId = '{!GETSESSIONID()}';
var result = sforce.connection.update([RCObj]);
if (result[0].getBoolean("success")) {
alert("Record Successfully Updated");
}
else {
alert("Failed to update RC " + result[0]);
}
//call the action fucntion to refresh the section of the page.
refreshPageBlock();
}catch (e) {
alert(e);
}
}
</script>
<apex:form>
<apex:actionFunction name="refreshPageBlock" id="actionFunciton" reRender="pgBlock"/>
<apex:pageBlock id="pgBlock">
<apex:pageBlockTable value="{!Parent__c.Child__r}" var="item" id="mid" title="Table 1">
<apex:column value="{!item.Type__c}"/>
<apex:column value="{!item.Status__c}"/>
<apex:column headerValue="Action">
<apex:commandLink value="Approve" id="Approve" onClick="DoSomething('{!item.id}','Approved')"/>
</apex:column>
</apex:pageBlockTable>
</apex:pageBlock>
</apex:form>
Best Answer
I got the solution. At the end of the save method, Im calling the method which fills my pageblocktable again. This way, after the records are saved, im re fetching the data to display. Because on re-render the records are not refreshed even though the pageblocktable is refreshed.