{"id":9809,"date":"2025-03-24T12:28:22","date_gmt":"2025-03-24T12:28:22","guid":{"rendered":"https:\/\/www.aegissofttech.com\/insights\/?p=9809"},"modified":"2025-09-24T11:22:46","modified_gmt":"2025-09-24T11:22:46","slug":"filter-sub-grid-rows-in-dynamics-365-ce-crm","status":"publish","type":"post","link":"https:\/\/www.aegissofttech.com\/insights\/filter-sub-grid-rows-in-dynamics-365-ce-crm\/","title":{"rendered":"How to Filter Sub-Grid Rows in Dynamics 365 CE (CRM) Using Fetch-XML &amp; JavaScript?"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\"><strong>INTRODUCTION<\/strong><\/h2>\n\n\n\n<p>Filtering sub-grids dynamically on model-driven forms is a common requirement in Dynamics 365 CRM implementations-especially when we want to present contextual data based on the record being viewed or edited. Out of the box, sub-grids offer limited flexibility for real-time filtering. However, by leveraging Fetch-XML and JavaScript, we can apply advanced filtering logic that adapts to business rules or user inputs on the fly. Such tailored solutions are often best implemented with the expertise of a <a href=\"https:\/\/www.aegissofttech.com\/dynamics-365\/crm\" target=\"_blank\" rel=\"noreferrer noopener\">Dynamics CRM Development Company<\/a>.<\/p>\n\n\n\n<p>In real-world CRM scenarios\u2014like sales forecasting, opportunity management, or customer service planning\u2014we often deal with interconnected tables and contextual views. Users expect the system to intelligently present related records without navigating away or manually filtering data. This is where programmatic control of sub-grid data becomes a game changer.<\/p>\n\n\n\n<p>This method helps ensure users are presented with the most relevant records based on their actions and selections, making the form behavior smarter and more efficient. Whether you&#8217;re customizing forms for Sales, Customer Service, or any other module, this approach gives us the precision and control needed for building intuitive and responsive UIs. By the end, you&#8217;ll have a clear understanding of how to implement custom filtering logic for sub-grids in your own Dynamics 365 CE environment.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong><em>PRE-REQUISITES<\/em><\/strong><em>:<\/em><\/h3>\n\n\n\n<ol style=\"list-style-type:lower-alpha\" class=\"wp-block-list\">\n<li>A Dataverse\/Dynamics 365 CE (CRM) environment<\/li>\n\n\n\n<li>System administrator \/ System Customizer role<\/li>\n\n\n\n<li>(Optional) Access to XRM Toolbox for JavaScript web-resources<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\"><strong><em>STEPS<\/em><\/strong><\/h3>\n\n\n\n<p>1. In our Dataverse Search \/ <a href=\"https:\/\/www.aegissofttech.com\/dynamics-365\/crm\" target=\"_blank\" rel=\"noreferrer noopener\">D365 CE<\/a> (CRM) environment, there exists a custom table named <em>Account Planning<\/em>. It has a lookup on it for <em>Account<\/em>. Despite there not being any relationship between <em>Account Planning <\/em>and <em>Opportunity<\/em> tables, we go ahead and place one Sub-grid for <em>Opportunities <\/em>on <em>Account Planning<\/em> form (as shown in the screenshot below). We then SAVE the changes.<\/p>\n\n\n\n<p><br><img decoding=\"async\" src=\"https:\/\/www.aegissofttech.com\/insights\/wp-content\/uploads\/2025\/03\/Dataverse-D365-CE-CRM-environment-1024x621.jpg\" alt=\"Dataverse D365 CE (CRM) environment\" title=\"\"><br><\/p>\n\n\n\n<p>2. Next, we create one JavaScript web-resource and put the following JS code in it. We all know that there exists an Out-of-the-Box 1: N relationship between <em>Accounts <\/em>and <em>Opportunities. <\/em>In simpler words, one Account can have multiple Opportunities. We can see in the highlighted content \u2013 we are making a filtration in the Fetch-XML, instructing to pull only those active Opportunities that belong to the selected account.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>IS.HPSAAccountPlanning.filterOpportunitiesSubgrid = function (formContext)\n{\n\tvar accountControl = formContext.getAttribute(\"infy_account\").getValue();\n\tif (accountControl)\n\t{\n\t\tvar accountId = accountControl&#91;0].id;\n\t\tvar fetchXml = \"&lt;fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'&gt;\" +\n\t\t\t\"&lt;entity name='opportunity'&gt;\" +\n\t\t\t\"&lt;attribute name='name' \/&gt;\" +\n\t\t\t\"&lt;filter type='and'&gt;\" +\n\t\t\t\"&lt;condition attribute='parentaccountid' operator='eq' uitype='account' value='\" + accountId + \"' \/&gt;\" +\n\t\t\t\"&lt;\/filter&gt;\" +\n\t\t\t\"&lt;\/entity&gt;\" +\n\t\t\t\"&lt;\/fetch&gt;\";\n\t\t\/\/ Set the fetchXml to the subgrid\n\t\tvar gridControl = formContext.getControl(\"subgrid_opportunities\");\n\t\tif (gridControl)\n\t\t{\n\t\t\tgridControl.setFilterXml(fetchXml);\n\t\t\tgridControl.refresh();\n\t\t}\n\t}\n}<\/code><\/pre>\n\n\n\n<p>3. After Saving &amp; Publishing the above JS web-resource, we add our function to the <em>On Load <\/em>Handler Property of the <em>Account Planning <\/em>form. Again, SAVE &amp; PUBLISH.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large Handler Properties\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"485\" src=\"https:\/\/www.aegissofttech.com\/insights\/wp-content\/uploads\/2025\/03\/On-Load-Handler-Property-1024x485.jpg\" alt=\"Handler Properties\" class=\"wp-image-9811\" title=\"\" srcset=\"https:\/\/www.aegissofttech.com\/insights\/wp-content\/uploads\/2025\/03\/On-Load-Handler-Property-1024x485.jpg 1024w, https:\/\/www.aegissofttech.com\/insights\/wp-content\/uploads\/2025\/03\/On-Load-Handler-Property-300x142.jpg 300w, https:\/\/www.aegissofttech.com\/insights\/wp-content\/uploads\/2025\/03\/On-Load-Handler-Property-768x364.jpg 768w, https:\/\/www.aegissofttech.com\/insights\/wp-content\/uploads\/2025\/03\/On-Load-Handler-Property.jpg 1362w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong><em>UNIT TESTITNG<\/em><\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>We create a new <em>Account Planning <\/em>record and select an Account on it.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"605\" height=\"252\" src=\"https:\/\/www.aegissofttech.com\/insights\/wp-content\/uploads\/2025\/03\/new-Account-Planning.jpg\" alt=\"New Account Planning\" class=\"wp-image-9812\" title=\"New Account Planning\" srcset=\"https:\/\/www.aegissofttech.com\/insights\/wp-content\/uploads\/2025\/03\/new-Account-Planning.jpg 605w, https:\/\/www.aegissofttech.com\/insights\/wp-content\/uploads\/2025\/03\/new-Account-Planning-300x125.jpg 300w\" sizes=\"(max-width: 605px) 100vw, 605px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>As we move to the tab where we have placed the <em>Opportunities <\/em>sub-grid, we verify that only the Opportunities that belong the selected Account get populated in the sub-grid.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"497\" src=\"https:\/\/www.aegissofttech.com\/insights\/wp-content\/uploads\/2025\/03\/Selected-Account-1024x497.jpg\" alt=\"\" class=\"wp-image-9813\" title=\"Selected Account\" srcset=\"https:\/\/www.aegissofttech.com\/insights\/wp-content\/uploads\/2025\/03\/Selected-Account-1024x497.jpg 1024w, https:\/\/www.aegissofttech.com\/insights\/wp-content\/uploads\/2025\/03\/Selected-Account-300x145.jpg 300w, https:\/\/www.aegissofttech.com\/insights\/wp-content\/uploads\/2025\/03\/Selected-Account-768x372.jpg 768w, https:\/\/www.aegissofttech.com\/insights\/wp-content\/uploads\/2025\/03\/Selected-Account.jpg 1355w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Conclusion<\/strong><\/h2>\n\n\n\n<p>In this blog, we explored a practical way to apply custom filters to a sub-grid using Fetch-XML and <a href=\"https:\/\/www.aegissofttech.com\/insights\/power-automate-flow-javascript-in-dynamics-365crm\/\" target=\"_blank\" rel=\"noreferrer noopener\">JavaScript in Dynamics 365<\/a> CE. While the platform provides basic sub-grid functionality out of the box, complex business requirements often demand more tailored experience.<\/p>\n\n\n\n<p>Through our example involving the Account Planning and Opportunity tables, we saw how even without a direct relationship, we can still show only the relevant child records, making the user interface more intuitive and aligned with the business context. With just a few lines of JavaScript and a well-formed Fetch-XML, we were able to dynamically filter sub-grid data based on the selected lookup value.<\/p>\n\n\n\n<p>This approach not only enhances user experience but also improves system performance by reducing clutter and ensuring that only meaningful data is displayed. It&#8217;s a lightweight yet powerful technique that every <a href=\"https:\/\/www.aegissofttech.com\/hire-ms-crm-developers.html\" target=\"_blank\" rel=\"noreferrer noopener\">Expert Dynamics 365 CRM developer<\/a> should have in their toolkit.<\/p>\n\n\n\n<p><strong>Read More:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.aegissofttech.com\/insights\/filter-in-dynamiccs-365-ce-canvas-apps\/\" data-type=\"link\" data-id=\"https:\/\/www.aegissofttech.com\/insights\/filter-in-dynamiccs-365-ce-canvas-apps\/\" target=\"_blank\" rel=\"noreferrer noopener\">Filtering Dynamics 365 CE in Canvas Apps with Option-Sets Tutorial<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.aegissofttech.com\/insights\/dynamics-365-ce-custom-api-from-3rd-party\/\">Consuming a Dynamics 365 CE Custom API from a 3rd Party<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":" ","protected":false},"author":11,"featured_media":9814,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[1173,21],"tags":[1272,1273,1274],"class_list":["post-9809","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dynamics-365-ce","category-dynamics-crm","tag-filter-sub-grid-rows-in-dynamics-365-ce","tag-filtering-sub-grids-dynamically","tag-sub-grid-using-fetch-xml-within-javascript"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/posts\/9809","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/users\/11"}],"replies":[{"embeddable":true,"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/comments?post=9809"}],"version-history":[{"count":9,"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/posts\/9809\/revisions"}],"predecessor-version":[{"id":14318,"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/posts\/9809\/revisions\/14318"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/media\/9814"}],"wp:attachment":[{"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/media?parent=9809"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/categories?post=9809"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.aegissofttech.com\/insights\/wp-json\/wp\/v2\/tags?post=9809"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}