We have the standard history for our fields in salesforce. We can use that functionality from the related list. Here we will see that functionality using component and apex class. This will be a generic code for custom objects. Just paste the id of the record for which you want to see history. Make sure you have enabled history tracking for that object.
Here is the apex class for JSON. Save this first.
HistoryWrapper.cls
public class HistoryWrapper{
public WrapperClass_attributes attributes;
public String CreatedById;
public datetime CreatedDate;
public String Field;
public boolean IsDeleted;
public string NewValue;
public string OldValue;
public String Id;
public Wrapperclass_CreatedBy CreatedBy;
public static list<HistoryWrapper> parse(String json){
return (list<HistoryWrapper>) System.JSON.deserialize(json, list<HistoryWrapper>.class);
}
public class WrapperClass_attributes {
public String type;
public String url;
}
public class Wrapperclass_CreatedBy {
public WrapperClass_attributes attributes;
public String Name;
public String FirstName;
public String LastName;
public String Id;
}
}
HistoryController.Cls
public class HistoryController{
public string query{get;set;}
public list<historywrap> recordsHistory{get;set;}
public string objectLabel{get;set;}
public HistoryController(){
recordsHistory=new list<historywrap>();
list<HistoryWrapper> parsedList=new list<HistoryWrapper>();
id parentId=apexpages.currentpage().getparameters().get('id');
if(parentId!=null ){
string sObjName = parentId.getSObjectType().getDescribe().getName();
Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
Schema.SObjectType ODSchema= schemaMap.get(sObjName);
Map<String, Schema.SObjectField> fieldMap = ODSchema.getDescribe().fields.getMap();
objectLabel= parentId.getSObjectType().getDescribe().getLabel();
sObjName =sObjName.replace('__c','__history');
if(schemaMap.get(sObjName)!=null){
query='SELECT CreatedBy.name,CreatedBy.Firstname,CreatedBy.Lastname,CreatedDate,Field,IsDeleted,NewValue,OldValue ';
query+='FROM '+ sObjName +' where parentId=\''+parentId+'\' and (Field!=\'locked\' and field!=\'unlocked\') order by createddate desc';
string outputget= JSON.serialize(database.query(query));
parsedList=HistoryWrapper.parse(outputget);
if(parsedList!=null && parsedList.size()>0){
for(HistoryWrapper ObjHistory :parsedList ){
if(ObjHistory.Field=='created'){
recordsHistory.add(new historywrap(ObjHistory.createdby.Name,ObjHistory.createddate,'Created','',''));
}else if(fieldMap.get(ObjHistory.field)!=null && ObjHistory.newvalue!=null){
if(string.valueof(fieldMap.get(ObjHistory.field).getDescribe().getSOAPType())=='ID' ){
if (! Pattern.compile( '[a-zA-Z0-9]{15}|[a-zA-Z0-9]{18}' ).matcher( ObjHistory.newValue).matches() ){
recordsHistory.add(new historywrap(ObjHistory.createdby.Name,ObjHistory.createddate,fieldMap.get(ObjHistory.field).getDescribe().getLabel(),ObjHistory.newvalue,ObjHistory.oldvalue));
}
}else{
recordsHistory.add(new historywrap(ObjHistory.createdby.Name,ObjHistory.createddate,fieldMap.get(ObjHistory.field).getDescribe().getLabel(),ObjHistory.newvalue,ObjHistory.oldvalue));
}
}
}
}
}
}
}
public class historywrap{
public string VUser{get;set;}
public string DateValue{get;set;}
public string Old{get;set;}
public string NewValue{get;set;}
public string Field{get;set;}
public historywrap(string usr, datetime dt, string fld, string nw, string ol){
this.vUser=usr;
this.DateValue=dt.format();
this.Field=fld;
this.NewValue=nw;
this.Old=ol;
}
}
}
VisualforceComponent:-
<apex:component controller="HistoryController">
<div class="slds-scope">
<div class="container-fluid slds-scrollable_x">
<div class="slds-section slds-is-open">
<h3 class="slds-section__title">
History
</h3>
<div class="slds-section__content">
<apex:pageBlock rendered="{!if(recordsHistory.size<=0,false,true)}" >
<table class="slds-table slds-table_cell-buffer slds-table_bordered">
<thead>
<tr class="slds-line-height_reset">
<th class="" scope="col">
<span class="slds-icon_container slds-m-right_xx-small slds-icon-custom-custom80" title="Description of icon when needed">
<svg class="slds-icon slds-icon_x-small" aria-hidden="true">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/apexpages/slds/latest/assets/icons/custom-sprite/svg/symbols.svg#custom80"></use>
</svg>
</span>
Last Modify By
</th>
<th class="" scope="col">
<span class="slds-icon_container slds-m-right_xx-small slds-icon-custom-custom24" title="Description of icon when needed">
<svg class="slds-icon slds-icon_x-small" aria-hidden="true">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/apexpages/slds/latest/assets/icons/custom-sprite/svg/symbols.svg#custom24"></use>
</svg>
</span>
Modified Date
</th>
<th class="" scope="col">
<span class="slds-icon_container slds-m-right_xx-small slds-icon-custom-custom66" title="Description of icon when needed">
<svg class="slds-icon slds-icon_x-small" aria-hidden="true">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/apexpages/slds/latest/assets/icons/custom-sprite/svg/symbols.svg#custom66"></use>
</svg>
</span>
Field
</th>
<th class="" scope="col">
<span class="slds-icon_container slds-m-right_xx-small slds-icon-custom-custom112" title="Description of icon when needed">
<svg class="slds-icon slds-icon_x-small" aria-hidden="true">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/apexpages/slds/latest/assets/icons/custom-sprite/svg/symbols.svg#custom112"></use>
</svg>
</span>
New Value
</th>
<th class="" scope="col">
<span class="slds-icon_container slds-m-right_xx-small slds-icon-custom-custom63" title="Description of icon when needed">
<svg class="slds-icon slds-icon_x-small" aria-hidden="true">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/apexpages/slds/latest/assets/icons/custom-sprite/svg/symbols.svg#custom63"></use>
</svg>
</span>
Old Value
</th>
</tr>
</thead>
<tbody>
<apex:repeat value="{!recordsHistory}" var="recordHistoryObj" >
<tr class="slds-hint-parent">
<th data-label="Action" scope="row">
<div class="slds-truncate" title="Cloudhub">{!recordHistoryObj.vUser}</div>
</th>
<td data-label="Signed By">
<div class="slds-truncate" title="4/14/2015"> <apex:outputText value="{0}">
<apex:param value="{!recordHistoryObj.DateValue}"/>
</apex:outputText> </div>
</td>
<td data-label="Prospecting">
<div class="slds-truncate" title="Prospecting">{!recordHistoryObj.Field}</div>
</td>
<td data-label="Comments">
<div class="slds-truncate" title="20%">{!recordHistoryObj.NewValue} </div>
</td>
<td data-label="Amount">
<div class="slds-truncate" title="$25k"><apex:outputText escape="false" value="{!recordHistoryObj.Old}" ></apex:outputText></div>
</td>
</tr>
</apex:repeat>
</tbody>
</table>
</apex:pageblock>
</div>
</div>
</div>
</div>
</apex:component>
Visualforce Page:-
<apex:page lightningStylesheets="true">
<apex:slds />
<c:CustomCodeHistory />
</apex:page>