[TIPS] 3 Ways to Filter Subgrid

 [TIPS] 3 Ways to Filter Subgrid

  1. View: Edit Filter Criteria
  2. JavaScript
  3. Plugin 

       View: Edit Filter Criteria
  • No customization
  • Out of the Box feature
JavaScript
  • Easier to implement
  • For medium complex requirements

Sample Code:

function onLoadFunction(executionContext)
{
    var formContext = executionContext.getFormContext(); // get the form context
    var tabContext = formContext.ui.tabs.get("tab_Bed_Assignment"); // get the tab context by its name
 
    // Register the event handler for the tab's state change event
    tabContext.addTabStateChange(filterSubgridBedAssignments);
    filterSubgridBedAssignments(executionContext);
 
   
   
}
 
function filterSubgridBedAssignments(executionContext)
{
    var formContext = executionContext.getFormContext();
    var currentBooking = formContext.getAttribute("tri_bookingid").getValue();
    var subgrid = formContext.getControl("subgrid_BedAssignments");
   
    //Check if Current Booking Lookup Field is not null
    if (currentBooking != null)
    {
        //Get Lookup Field Id
        var currentBookingId = currentBooking[0].id.replace("{", "").replace("}", "");
 
        if (subgrid)
        {
            //Set Filter XML for Subgrid
            var fetchXml = "<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>"
            + "<entity name='tri_bedassignment'>"
            + "<filter type='and'>"
            + "<condition attribute='tri_bookingid' operator='eq' value='" + currentBookingId + "' />"
            + "</filter>"
            + "</entity>"
            + "</fetch>";
 
            subgrid.setFilterXml(fetchXml);
            subgrid.refresh();
        }        
    }
    else
    {
        subgrid.setVisible(false);
    }
}


Plugin
  • For higher complex requirements

Sample Code:

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

public class Filter_MovementsPlugin : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
        IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
        IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
        ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

        tracingService.Trace("Filter_MovementsPlugin: Plugin started.");

        if (context.InputParameters.Contains("Query") && context.InputParameters["Query"] is FetchExpression fetchExpression)
        {
            var fetchXmlDoc = XDocument.Parse(fetchExpression.Query);
            var entityNode = fetchXmlDoc.Descendants("entity").FirstOrDefault();
            var attributeLatestOnly = fetchXmlDoc.Descendants("attribute").FirstOrDefault(attr => attr.Attribute("name")?.Value == "kc_latestonly");

            if (attributeLatestOnly == null)
            {
                tracingService.Trace("Filter_MovementsPlugin: required attribute not found in FetchXML query. Skipping Latest Movement Filter plugin execution.");
                return;
            }

            if (entityNode != null && entityNode.Attribute("name")?.Value == "tri_offendermovement")
            {
                tracingService.Trace("Filter_MovementsPlugin: tri_offendermovement entity found.");

                EntityCollection originalResults = context.OutputParameters["BusinessEntityCollection"] as EntityCollection;

                // Filter the original results to include only the latest created records for each subject
                var modifiedResults = new EntityCollection();
                modifiedResults.EntityName = "tri_offendermovement";

                var subjects = originalResults.Entities.Select(e => e.GetAttributeValue<EntityReference>("tri_offenderid")).Distinct();

                foreach (var subject in subjects)
                {
                    var subjectId = subject.Id;

                    // Get the latest created record for each subject from the original results
                    var latestCreatedEntity = originalResults.Entities
                        .Where(e => e.GetAttributeValue<EntityReference>("tri_offenderid").Id == subjectId)
                        .OrderByDescending(e => e.GetAttributeValue<DateTime>("createdon"))
                        .FirstOrDefault();

                    if (latestCreatedEntity != null)
                    {
                        modifiedResults.Entities.Add(latestCreatedEntity);
                    }
                }

                // Set the modified results as the output of the RetrieveMultiple message
                context.OutputParameters["BusinessEntityCollection"] = modifiedResults;
            }
            else
            {
                tracingService.Trace("Filter_MovementsPlugin: tri_offendermovement entity not found.");
            }
        }
        else
        {
            tracingService.Trace("Filter_MovementsPlugin: FetchExpression not detected.");
        }
        tracingService.Trace("Filter_MovementsPlugin: Plugin execution completed.");
    }
}