I have a requirement to be able to search a record(document) in the record center based on a calculation. I can not store the calculated value as part of the item properties because an update of the property would constitute a change the item that is now immutable. Is it possible to leverage Content Enrichment or some other method to add to the index?


A record has a date (RecordDate) and text field (RecordText). I need to be able to search, filter, and refine on the condition that the date is greater than or equal to today OR the text field contains a specific value "ABC".

Solution: A radio button search refiner (Active, Inactive, All). All is the default and adds nothing to the search filter. Active adds a filter of (RecordDate>={Today} OR RecordText="ABC") and Inactive adds filter (RecordDate<{Today} AND RecordText<>"ABC").

I appreciate any help you can provide.

2 Answers 2


If you are using SharePoint 2013 or 2016 this is not difficult. Lets assume that your date field is "RecordDate" and the text field is "RecordText". If you create a managed property of the same name for each you should be able to use the query RecordDate>={Today} OR RecordText="ABC"

  • Thank you for your reply. You are correct that this effectively achieves the search result. I forgot to clarify that we would like to be able to refine/filter on the true or false evaluation result of (RecordDate>={Today} OR RecordText="ABC") in a search screen. This is where I am struggling.
    – JonesEJ
    May 26, 2016 at 12:11
  • I don't understand. Though you can write a custom refiner to work any way you like. May 26, 2016 at 16:06
  • I guess this is exactly what i am asking. If a custom refiner is the solution how do I create one that evaluates 2 columns. My desired end result is an (Active, Inactive, All) radio button where Active adds a filter of (RecordDate>={Today} OR RecordText="ABC") and Inactive adds filter (RecordDate<{Today} AND RecordText<>"ABC") and All removes the filter.
    – JonesEJ
    May 27, 2016 at 0:06
  • I don't know, I haven't tried to do that. May 27, 2016 at 20:55
  • I posted the solution I used, would love your input.
    – JonesEJ
    Jun 16, 2016 at 22:33

This was accomplished by creating a custom refiner. The code used was:

The supporting JavaScript file (My_Filter_InactiveActive_functions.js) was

function applyActiveInactiveRefiner(val, refinementCtrl, refinerName, strQuery){    
var refiners = {};
refiners[refinerName] = null;
refinementCtrl.updateRefiners( refiners );
if (val == 1){ // Active 
    strRefinerValue = 'not(' + strQuery + ')';
    refiners[refinerName] = [strRefinerValue];
else if (val == 2) // Inactive
    refiners[refinerName] = [strQuery];
refinementCtrl.updateRefiners(refiners, 'or', false, null);


The refiner code file (My_Filter_InactiveActive.html) was My Refiner - Inactive / Active Status

<!--[if gte mso 9]><xml>
<mso:CompatibleManagedProperties msdt:dt="string"></mso:CompatibleManagedProperties>
<mso:TemplateHidden msdt:dt="string">0</mso:TemplateHidden>
<mso:CompatibleSearchDataTypes msdt:dt="string"></mso:CompatibleSearchDataTypes>
<mso:MasterPageDescription msdt:dt="string"></mso:MasterPageDescription>
<mso:ContentTypeId msdt:dt="string">0x0101002039C03B61C64EC4A04F5361F385106604</mso:ContentTypeId>
<mso:TargetControlType msdt:dt="string">;#Refinement;#</mso:TargetControlType>
<mso:HtmlDesignAssociated msdt:dt="string">1</mso:HtmlDesignAssociated>

$includeScript(this.url, "~sitecollection/_catalogs/masterpage/display templates/filters/EDF_Filter_InactiveActive_functions.js");

   <div id="InactiveActiveStatusRefinement">
  // Needed objects
  var listData = ctx.ListData;
  var hasControl = true;

  // Create a new hidden block outside the current refinement control
  var refElm = document.getElementById('Refinement');
  var hiddenBlockID = ctx.RefinementControl.containerId + "_" + ctx.RefinementControl.propertyName;
  var hiddenBlock = document.getElementById(hiddenBlockID);
  // Check if the hidden block exists, otherwise we create one
  if (hiddenBlock === null || hiddenBlock.lenght <= 0) {
    hiddenBlock = document.createElement('div');
    hiddenBlock.setAttribute('id', hiddenBlockID);
    hiddenBlock.setAttribute('style', 'display:none;');

  var currentRefinementCategory = ctx.ClientControl.getCurrentRefinementCategory(ctx.RefinementControl.propertyName);
  // Check if the object is null or undefined && Count the tokens currently in place
  var hasAnyFiltertokens = (!Srch.U.n(currentRefinementCategory) && currentRefinementCategory.get_tokenCount() > 0);
  var numFiltertokens = 0;
    numFiltertokens = currentRefinementCategory.get_tokenCount();

  // Check if the current Refinement Control can be exists
  if ($isNull(ctx.RefinementControl) || $isNull(ctx.ClientControl)) hasControl = false;

  if (hasControl) {
    if(!$isNull(listData) && !$isEmptyArray(listData)) {
        // Show the refinement title
        var isExpanded = Srch.Refinement.getExpanded(ctx.RefinementControl.propertyName);
        var iconClass = (isExpanded == "true"? "ms-ref-uparrow" : "ms-ref-downarrow");
        var refinerCatTitle = Srch.Refinement.getRefinementTitle(ctx.RefinementControl);
        // Display style > needed to hide the refinement list when collapsed
        var displayStyle = (isExpanded == "true"? "" : "none");
        var today = new Date();

        var strQuery = 'and(' + ctx.RefinementControl.propertyName + ':range(min, '+ today.toISOString() +'),RecordText:not(&quot;No Expiration&quot;))'
        <div id='Container'>
            _#= Srch.U.collapsibleRefinerTitle(ctx.RefinementControl.propertyName, ctx.ClientControl.get_id(), refinerCatTitle, iconClass) =#_
         <select class="ms-ref-unselSec" id="InactiveActiveStatusDdl" onchange="javascript:applyActiveInactiveRefiner(this.value, $getClientControl(this), '_#= ctx.RefinementControl.propertyName =#_', '_#= strQuery =#_ ');">

strHash = decodeURIComponent(window.location.hash);
strSelected = 'All';
  if(strHash.indexOf(ctx.RefinementControl.propertyName +'","t":["not(') > 0){
    strSelected = 'Active';
  else if(strHash.indexOf(ctx.RefinementControl.propertyName +'","t":[') > 0){
    strSelected = 'Inactive';

  addRefiner(0, 'All', strSelected=='All');
  addRefiner(1, 'Active', strSelected=='Active');
  addRefiner(2, 'Inactive', strSelected=='Inactive');

    <div id="RemoveRefinement">

    if(strSelected != 'All'){
        var refinerRemoval = new Object();
        refinerRemoval[ctx.RefinementControl.propertyName] = null;
        ShowRefiner('Remove refinement', null, refinerRemoval, 'updateRefinersJSON', false);
   function addRefiner(val, text, selected) {
      if (selected) {
         <option selected="selected" value="_#= val =#_">_#= text =#_</option>
      } else {
         <option value="_#= val =#_">_#= text =#_</option>

   function ShowRefiner(refinementName, refinementCount, refiners, method, selected) {
        // Create the onClick or onChange event
        var onChangeOrClick = "$getClientControl(document.getElementById('"+ctx.RefinementControl.containerId+"'))." + method + "('" + $scriptEncode(Sys.Serialization.JavaScriptSerializer.serialize(refiners)) + "');";

        // Check if there aren't filter tokens in place
        if (!hasAnyFiltertokens) {
            var elm = document.getElementById(hiddenBlockID);
            var option = document.createElement('option');
            var text = document.createTextNode(refinementName);
            option.setAttribute('value', onChangeOrClick);

        // Check if the refinement contains results && if the current item is selected
        if (refinementCount != null && selected !== true) {
           <option value='_#= onChangeOrClick =#_'>_#= $htmlEncode(refinementName) =#_</option>
        } else if (refinementCount != null && selected === true) {
           <option value='_#= onChangeOrClick =#_' selected='selected'>_#= $htmlEncode(refinementName) =#_</option>
        } else {
            <div><a href='javascript:{}' onclick='_#= onChangeOrClick =#_'>_#= $htmlEncode(refinementName) =#_</a></div>



Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.