Pagination Methods in Dynamics 365 Integration: An In-Depth Guide

 

Pagination Methods in Dynamics 365 Integration: An In-Depth Guide

Introduction

When working with Dynamics 365, especially when integrating it with other systems, you'll often have to retrieve large sets of data. However, due to performance considerations, APIs usually impose a limit on the number of records you can fetch in a single request. This necessitates the use of pagination to get the entire dataset. This guide aims to provide a comprehensive understanding of different pagination methods, their advantages and drawbacks, and how to apply them in Dynamics 365 integration scenarios.

Hiding a Button Based on Row Count in Subgrid for Power Apps Portal

Hiding a Button Based on Row Count in Subgrid for Power Apps Portal

Introduction

The ability to display or hide buttons based on the number of rows in a subgrid can be quite a useful feature in Power Apps Portal. This article will elaborate on two scenarios:

  • When the button redirects to a webpage
  • When the button targets a basic form

We will also introduce a reusable function checkSubgridAndHideButton that can be used for any subgrid and button.

[TIP] Filtering Subgrid Data in Dynamics 365 Portal Using JavaScript

 

Filtering Subgrid Data in Dynamics 365 Portal Using JavaScript

Introduction

In this blog, we'll explore a hands-on approach to filtering subgrid data in the Dynamics 365 Portal using JavaScript. While server-side plugins and client-side plugins offer solutions to similar challenges, sometimes a JavaScript-only solution is necessary due to limitations or specific project needs.

[Sample Code] Google Places API integrate with Microsoft Dynamics 365

 [Sample Code] Google Places API integrate with Microsoft Dynamics 365 

Understanding Promise Constructors in JavaScript

Understanding Promise Constructors in JavaScript

Introduction

JavaScript's asynchronous programming is often associated with callbacks and the "callback hell." However, with the introduction of Promises, managing asynchronous operations became more straightforward and more readable. A Promise in JavaScript represents a value that may not be available yet but will be resolved at some point in the future. In this post, we'll dive into the concept of Promises, understanding their states, usage, and how to handle different outcomes.

Dataverse REST Builder


Dataverse REST Builder


Create and Execute requests against the Dataverse Web API endpoint.
Dataverse REST Builder allows to create and execute requests against the Dataverse Web API endpoint. After obtaining the token from the authentication process (a Dataverse instance is required and a URL must be provided) the tool is loaded and a new collection of requests can be created.

Sorting an Array of JavaScript Objects by Date

 Sorting an Array of JavaScript Objects by Date

In JavaScript, arrays are one of the most common data structures you will work with, and from time to time, you might find the need to sort them. The Array.prototype.sort() method is the built-in JavaScript function that helps us sort the elements of an array. By default, this function sorts arrays lexicographically (alphabetically) based on the string conversion of each element.

However, what if we want to sort an array of objects based on a date field? Let's take an array of alert objects for example, where each alert object has a createdon field representing the date it was created. We can utilize the sort() method and provide a custom comparator function to sort these objects.

Understanding JavaScript Objects: Adding and Accessing Dynamic Properties

 

Understanding JavaScript Objects: Adding and Accessing Dynamic Properties

JavaScript is a dynamic language, and one of its most versatile features is the ability to deal with objects. In this post, we will delve into the specifics of how we can dynamically add and access properties in a JavaScript object.

Customize Main Form Button in Model-driven App Using Ribbon Workbench

 

Customize Main Form Button in Model-driven App Using Ribbon Workbench

Sample JavaScript Code:

Custom Subgrid Button in Model-driven App Using Power Platform OOB + JavaScript + Power Automate

 Custom Subgrid Button in Model-driven App Using Power Platform OOB + JavaScript + Power Automate

JavaScript Sample Code:

Display rule - ValueRule introduction

 Display rule in Ribbon Workbench - show or hide a ribbon button based on the value of a field on the record. 

Administration mode for a Microsoft Dynamics 365 (D365) environment

 Administration mode for a Microsoft Dynamics 365 (D365) environment

[TIP] How to rename the column name in subgrid of Power Pages/Power Apps Portal

 [TIP] How to rename the column name in subgrid of Power Pages/Power Apps Portal

In Power Pages/Power Apps Portal, sometimes we may need to change the column names in the subgrid.

[TIP] Workaround for Multi-Select Parameters in SSRS for Dynamics 365

 Workaround for Multi-Select Parameters in SSRS for Dynamics 365

Education accelerator

Education accelerator

How to Change Logo of Power Apps Portal (or Power Pages)

 How to Change Logo of Power Apps Portal (or Power Pages)

How to convert UTC time to Local time in Dynamics 365 using JavaScript

 How to convert UTC time to Local time in Dynamics 365 using JavaScript

[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.");
    }
}




[TIPS] How to get Attribute/Field value without executionContext input

 [TIPS] How to get Attribute/Field value without executionContext input

[TIPS] Difference between formContext.data.entity.addOnLoad() and Add function to form on load event directly

 [TIPS] Difference between formContext.data.entity.addOnLoad() and Add function to form on load event directly

[TIPS] Difference between Team privileges only and Direct User/Basic access level and Team privileges in Dynamics 365 Security Role Setting

 [TIPS] Difference between Team privileges only and Direct User/Basic access level and Team privileges in Dynamics 365 Security Role Setting

Reference: 1

[TIPS] Dynamics 365 / Power Apps / Power Platform Version Control

 [TIPS] Dynamics 365 / Power Apps / Power Platform Version Control

Reference: 1