diff --git a/README.md b/README.md index 7401dc9..434d74f 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,37 @@ A robust framework tailored for Dynamics 365 Client API. While crafted with Type XrmEx offers a comprehensive suite of wrappers that seamlessly integrate the Dynamics 365 Client API, ensuring developers have a smooth experience. Dive into XrmEx and elevate your productivity, channeling your energy into crafting exceptional applications. +- [Xrm-Ex: Dynamics 365 Xrm Extensions](#xrm-ex-dynamics-365-xrm-extensions) + - [Installation](#installation) + - [Getting Started](#getting-started) + - [Documentation](#documentation) + - [Contribution Guidelines](#contribution-guidelines) +- [Why Use the XrmEx Library?](#why-use-the-xrmex-library) + - [1. Event Handling](#1-event-handling) + - [Without XrmEx:](#without-xrmex) + - [With XrmEx:](#with-xrmex) + - [2. Field Changes and Events](#2-field-changes-and-events) + - [Without XrmEx:](#without-xrmex-1) + - [With XrmEx:](#with-xrmex-1) + - [3. Form Types and Field Requirements](#3-form-types-and-field-requirements) + - [Without XrmEx:](#without-xrmex-2) + - [With XrmEx:](#with-xrmex-2) + - [4. Data Retrieval and Setting](#4-data-retrieval-and-setting) + - [Without XrmEx:](#without-xrmex-3) + - [With XrmEx:](#with-xrmex-3) + - [Advanced Features](#advanced-features) + - [1. Lookup Filters](#1-lookup-filters) + - [Without XrmEx:](#without-xrmex-4) + - [With XrmEx:](#with-xrmex-4) + - [2. Advanced Lookup Filter](#2-advanced-lookup-filter) + - [Special with XrmEx: Supports entire FetchXml including Link-Entity!](#special-with-xrmex-supports-entire-fetchxml-including-link-entity) + - [3. Execute Bound Action](#3-execute-bound-action) + - [Without XrmEx:](#without-xrmex-5) + - [With XrmEx:](#with-xrmex-5) + - [4. Retrieve EnvironmentVariableValue](#4-retrieve-environmentvariablevalue) + - [Without XrmEx:](#without-xrmex-6) + - [With XrmEx:](#with-xrmex-6) + ## Installation XrmEx can be easily installed via npm: ```shell @@ -88,7 +119,6 @@ YourNamespace.ContactFunctions = { } }; ``` - ## Documentation For a comprehensive guide to using XrmEx, please check out the full [documentation](https://github.com/AhashSritharan/Xrm-Ex/blob/main/docs/modules/XrmEx.md). @@ -105,4 +135,263 @@ For more information, please see our [contribution guide](https://github.com/Aha XrmEx is released as an open-source project. We welcome contributions from the developer community. Whether it's a bug report, new feature, or a correction, we greatly appreciate any help you can provide. -Leverage the power of Dynamics 365 Client API with less code and fewer errors. Get started with XrmEx today! \ No newline at end of file +Leverage the power of Dynamics 365 Client API with less code and fewer errors. Get started with XrmEx today! + +Why Use the XrmEx Library? +========================== + +When developing for Dynamics 365, efficiency, clarity, and maintainability are paramount. The XrmEx library is designed to streamline your coding experience, making it more intuitive and less error-prone. Let's delve into some examples to illustrate the transformative power of XrmEx: + + +1\. Event Handling +------------------ + +### Without XrmEx: + +```js +formContext.data.entity.addOnSave(sample); +``` +### With XrmEx: + +```js +XrmEx.Form.addOnSaveEventHandler([sample]); +``` +The XrmEx approach is more concise and offers a clearer intent, especially when registering multiple functions. + +2\. Field Changes and Events +---------------------------- + +### Without XrmEx: + +```js +let firstname = formContext.getAttribute("firstname"); +let lastname = formContext.getAttribute("lastname"); +firstname.addOnChange(sample); +firstname.fireOnChange(); +lastname.fireOnChange(); +``` +### With XrmEx: + +```js +XrmEx.Form.addOnChangeEventHandler( + [fields.Firstname, fields.Lastname], + [sample], + true //fireOnChange +); +``` +With XrmEx, you can handle multiple fields and events in a single line, making the code cleaner and more maintainable. + +3\. Form Types and Field Requirements +------------------------------------- + +### Without XrmEx: + +```js +if (formContext.ui.getFormType() != 2) return; +let firstname = formContext.getAttribute("firstname"); +if (!firstname.getValue()) { + firstname.setRequiredLevel("required"); + firstname.controls.forEach((c) => + c.setNotification("This property is required", "uniqueId") + ); +} +``` +### With XrmEx: + +```js +if (XrmEx.Form.IsNotUpdate) return; +if (!fields.Firstname.Value) + fields.Firstname.setRequired(true).setNotification( + "This property is required","uniqueId"); +``` +XrmEx provides intuitive methods that simplify common tasks, like checking form types or setting field requirements. You don't have to use the redundant `forEach` anymore. + +4\. Data Retrieval and Setting +------------------------------ + +### Without XrmEx: + +```js +let ownerid = formContext.getAttribute("ownerid"); +let lastname = formContext.getAttribute("lastname"); +if (ownerid.getValue() && !lastname.getValue()) { + let user = await Xrm.WebApi.retrieveRecord( + ownerid.getValue()[0].entityType, + ownerid.getValue()[0].id, + "?$select=lastname" + ); + lastname.setValue(user.lastname); +} +``` +### With XrmEx: + +```js +if (fields.Owner.Value && !fields.Lastname.Value) { + let user = await fields.Owner.retrieve("?$select=lastname");//Returns null if empty + fields.Lastname.Value = user.lastname; + fields.Lastname.setValue(user.lastname); +} +``` +XrmEx abstracts away the complexities of data retrieval, making it more straightforward and readable. + +Advanced Features +----------------- + +### 1\. Lookup Filters + +#### Without XrmEx: + +```js +let filterFunction = function filterFunction(executionContext: Xrm.Events.EventContext) { + let formContext = executionContext.getFormContext(); + let customer: Xrm.Attributes.LookupAttribute = formContext.getAttribute("parentcustomerid"); + customer.controls.forEach((c) => { + c.addCustomFilter( + ` + + ` + ); + }); +}; +let customer: Xrm.Attributes.LookupAttribute = formContext.getAttribute("parentcustomerid"); +customer.controls.forEach((c) => c.addPreSearch(filterFunction)); +customer.controls.forEach((c) => c.removePreSearch(filterFunction)); +``` +#### With XrmEx: + +```js +fields.Customer.addPreFilterToLookup( + ` + + ` +); +fields.Customer.clearPreFilterFromLookup(); //Removes all filter added with addPreFilterToLookup or addPreFilterToLookupAdvanced +``` +### 2\. Advanced Lookup Filter + +#### Special with XrmEx: Supports entire FetchXml including Link-Entity! + +```js +await fields.Customer.addPreFilterToLookupAdvanced( + "contact",//entityname + "contactid",//entity unique identifier name + ` + + + + + + + + + + + ` +); +``` +### 3\. Execute Bound Action + +#### Without XrmEx: + +```js +class TestActionContactRequest { +Amount: 0; +Account: null; +getMetadata() { + return { + boundParameter: "entity", + operationType: 0, + operationName: "theia_TestActionContact", + parameterTypes: { + Amount: { + typeName: "Edm.Int32", + structuralProperty: 1, + }, + Account: { + typeName: "mscrm.account", + structuralProperty: 5, + }, + entity: { + typeName: "mscrm.contact", + structuralProperty: 5, + }, + }, + }; +} +} +let testActionContactRequest = new TestActionContactRequest(); +testActionContactRequest.Amount = 5; +testActionContactRequest.Account = customer.getValue()[0]; +testActionContactRequest["entity"] = +formContext.data.entity.getEntityReference(); +let response = await Xrm.WebApi.online.execute(testActionContactRequest) + .then(function (response) { + if (response.ok) { + return response.json().catch(() => { + return response; + }); + } + }) + .then((responseBody) => responseBody); +console.log(response); +``` +#### With XrmEx: + +```js +let response2 = await XrmEx.executeAction( + "theia_TestActionContact", + [ + { Name: "Amount", Type: "Integer", Value: 5 }, + { + Name: "Account", + Type: "EntityReference", + Value: fields.Customer.Value[0], + }, + ], + XrmEx.Form.entityReference +); +console.log(response2); +``` +### 4\. Retrieve EnvironmentVariableValue + +#### Without XrmEx: + +```js +class EnvironmentVariableRequest { +DefinitionSchemaName: ""; +constructor(definitionSchemaName) { + this.DefinitionSchemaName = definitionSchemaName; +} +getMetadata() { + return { + boundParameter: null, + operationType: 1, + operationName: "RetrieveEnvironmentVariableValue", + parameterTypes: { + DefinitionSchemaName: { + typeName: "Edm.String", + structuralProperty: 1, + }, + }, + }; +} +} +let environmentVariableRequest = new EnvironmentVariableRequest("theia_Test"); +let value = await Xrm.WebApi.online.execute(environmentVariableRequest) + .then(function (response) { + if (response.ok) { + return response.json().catch(() => { + return response; + }); + } + }) + .then((responseBody) => responseBody); +console.log(value); +``` +#### With XrmEx: + +```js +let value2 = await XrmEx.getEnvironmentVariableValue("theia_Test"); +console.log(value2); +``` +**In Conclusion:** The advanced features of the XrmEx library further exemplify its power in simplifying and enhancing the Dynamics 365 development experience. By abstracting away the complexities, developers can focus on the core logic and functionality of their applications. \ No newline at end of file diff --git a/build/README.md b/build/README.md index 7401dc9..434d74f 100644 --- a/build/README.md +++ b/build/README.md @@ -9,6 +9,37 @@ A robust framework tailored for Dynamics 365 Client API. While crafted with Type XrmEx offers a comprehensive suite of wrappers that seamlessly integrate the Dynamics 365 Client API, ensuring developers have a smooth experience. Dive into XrmEx and elevate your productivity, channeling your energy into crafting exceptional applications. +- [Xrm-Ex: Dynamics 365 Xrm Extensions](#xrm-ex-dynamics-365-xrm-extensions) + - [Installation](#installation) + - [Getting Started](#getting-started) + - [Documentation](#documentation) + - [Contribution Guidelines](#contribution-guidelines) +- [Why Use the XrmEx Library?](#why-use-the-xrmex-library) + - [1. Event Handling](#1-event-handling) + - [Without XrmEx:](#without-xrmex) + - [With XrmEx:](#with-xrmex) + - [2. Field Changes and Events](#2-field-changes-and-events) + - [Without XrmEx:](#without-xrmex-1) + - [With XrmEx:](#with-xrmex-1) + - [3. Form Types and Field Requirements](#3-form-types-and-field-requirements) + - [Without XrmEx:](#without-xrmex-2) + - [With XrmEx:](#with-xrmex-2) + - [4. Data Retrieval and Setting](#4-data-retrieval-and-setting) + - [Without XrmEx:](#without-xrmex-3) + - [With XrmEx:](#with-xrmex-3) + - [Advanced Features](#advanced-features) + - [1. Lookup Filters](#1-lookup-filters) + - [Without XrmEx:](#without-xrmex-4) + - [With XrmEx:](#with-xrmex-4) + - [2. Advanced Lookup Filter](#2-advanced-lookup-filter) + - [Special with XrmEx: Supports entire FetchXml including Link-Entity!](#special-with-xrmex-supports-entire-fetchxml-including-link-entity) + - [3. Execute Bound Action](#3-execute-bound-action) + - [Without XrmEx:](#without-xrmex-5) + - [With XrmEx:](#with-xrmex-5) + - [4. Retrieve EnvironmentVariableValue](#4-retrieve-environmentvariablevalue) + - [Without XrmEx:](#without-xrmex-6) + - [With XrmEx:](#with-xrmex-6) + ## Installation XrmEx can be easily installed via npm: ```shell @@ -88,7 +119,6 @@ YourNamespace.ContactFunctions = { } }; ``` - ## Documentation For a comprehensive guide to using XrmEx, please check out the full [documentation](https://github.com/AhashSritharan/Xrm-Ex/blob/main/docs/modules/XrmEx.md). @@ -105,4 +135,263 @@ For more information, please see our [contribution guide](https://github.com/Aha XrmEx is released as an open-source project. We welcome contributions from the developer community. Whether it's a bug report, new feature, or a correction, we greatly appreciate any help you can provide. -Leverage the power of Dynamics 365 Client API with less code and fewer errors. Get started with XrmEx today! \ No newline at end of file +Leverage the power of Dynamics 365 Client API with less code and fewer errors. Get started with XrmEx today! + +Why Use the XrmEx Library? +========================== + +When developing for Dynamics 365, efficiency, clarity, and maintainability are paramount. The XrmEx library is designed to streamline your coding experience, making it more intuitive and less error-prone. Let's delve into some examples to illustrate the transformative power of XrmEx: + + +1\. Event Handling +------------------ + +### Without XrmEx: + +```js +formContext.data.entity.addOnSave(sample); +``` +### With XrmEx: + +```js +XrmEx.Form.addOnSaveEventHandler([sample]); +``` +The XrmEx approach is more concise and offers a clearer intent, especially when registering multiple functions. + +2\. Field Changes and Events +---------------------------- + +### Without XrmEx: + +```js +let firstname = formContext.getAttribute("firstname"); +let lastname = formContext.getAttribute("lastname"); +firstname.addOnChange(sample); +firstname.fireOnChange(); +lastname.fireOnChange(); +``` +### With XrmEx: + +```js +XrmEx.Form.addOnChangeEventHandler( + [fields.Firstname, fields.Lastname], + [sample], + true //fireOnChange +); +``` +With XrmEx, you can handle multiple fields and events in a single line, making the code cleaner and more maintainable. + +3\. Form Types and Field Requirements +------------------------------------- + +### Without XrmEx: + +```js +if (formContext.ui.getFormType() != 2) return; +let firstname = formContext.getAttribute("firstname"); +if (!firstname.getValue()) { + firstname.setRequiredLevel("required"); + firstname.controls.forEach((c) => + c.setNotification("This property is required", "uniqueId") + ); +} +``` +### With XrmEx: + +```js +if (XrmEx.Form.IsNotUpdate) return; +if (!fields.Firstname.Value) + fields.Firstname.setRequired(true).setNotification( + "This property is required","uniqueId"); +``` +XrmEx provides intuitive methods that simplify common tasks, like checking form types or setting field requirements. You don't have to use the redundant `forEach` anymore. + +4\. Data Retrieval and Setting +------------------------------ + +### Without XrmEx: + +```js +let ownerid = formContext.getAttribute("ownerid"); +let lastname = formContext.getAttribute("lastname"); +if (ownerid.getValue() && !lastname.getValue()) { + let user = await Xrm.WebApi.retrieveRecord( + ownerid.getValue()[0].entityType, + ownerid.getValue()[0].id, + "?$select=lastname" + ); + lastname.setValue(user.lastname); +} +``` +### With XrmEx: + +```js +if (fields.Owner.Value && !fields.Lastname.Value) { + let user = await fields.Owner.retrieve("?$select=lastname");//Returns null if empty + fields.Lastname.Value = user.lastname; + fields.Lastname.setValue(user.lastname); +} +``` +XrmEx abstracts away the complexities of data retrieval, making it more straightforward and readable. + +Advanced Features +----------------- + +### 1\. Lookup Filters + +#### Without XrmEx: + +```js +let filterFunction = function filterFunction(executionContext: Xrm.Events.EventContext) { + let formContext = executionContext.getFormContext(); + let customer: Xrm.Attributes.LookupAttribute = formContext.getAttribute("parentcustomerid"); + customer.controls.forEach((c) => { + c.addCustomFilter( + ` + + ` + ); + }); +}; +let customer: Xrm.Attributes.LookupAttribute = formContext.getAttribute("parentcustomerid"); +customer.controls.forEach((c) => c.addPreSearch(filterFunction)); +customer.controls.forEach((c) => c.removePreSearch(filterFunction)); +``` +#### With XrmEx: + +```js +fields.Customer.addPreFilterToLookup( + ` + + ` +); +fields.Customer.clearPreFilterFromLookup(); //Removes all filter added with addPreFilterToLookup or addPreFilterToLookupAdvanced +``` +### 2\. Advanced Lookup Filter + +#### Special with XrmEx: Supports entire FetchXml including Link-Entity! + +```js +await fields.Customer.addPreFilterToLookupAdvanced( + "contact",//entityname + "contactid",//entity unique identifier name + ` + + + + + + + + + + + ` +); +``` +### 3\. Execute Bound Action + +#### Without XrmEx: + +```js +class TestActionContactRequest { +Amount: 0; +Account: null; +getMetadata() { + return { + boundParameter: "entity", + operationType: 0, + operationName: "theia_TestActionContact", + parameterTypes: { + Amount: { + typeName: "Edm.Int32", + structuralProperty: 1, + }, + Account: { + typeName: "mscrm.account", + structuralProperty: 5, + }, + entity: { + typeName: "mscrm.contact", + structuralProperty: 5, + }, + }, + }; +} +} +let testActionContactRequest = new TestActionContactRequest(); +testActionContactRequest.Amount = 5; +testActionContactRequest.Account = customer.getValue()[0]; +testActionContactRequest["entity"] = +formContext.data.entity.getEntityReference(); +let response = await Xrm.WebApi.online.execute(testActionContactRequest) + .then(function (response) { + if (response.ok) { + return response.json().catch(() => { + return response; + }); + } + }) + .then((responseBody) => responseBody); +console.log(response); +``` +#### With XrmEx: + +```js +let response2 = await XrmEx.executeAction( + "theia_TestActionContact", + [ + { Name: "Amount", Type: "Integer", Value: 5 }, + { + Name: "Account", + Type: "EntityReference", + Value: fields.Customer.Value[0], + }, + ], + XrmEx.Form.entityReference +); +console.log(response2); +``` +### 4\. Retrieve EnvironmentVariableValue + +#### Without XrmEx: + +```js +class EnvironmentVariableRequest { +DefinitionSchemaName: ""; +constructor(definitionSchemaName) { + this.DefinitionSchemaName = definitionSchemaName; +} +getMetadata() { + return { + boundParameter: null, + operationType: 1, + operationName: "RetrieveEnvironmentVariableValue", + parameterTypes: { + DefinitionSchemaName: { + typeName: "Edm.String", + structuralProperty: 1, + }, + }, + }; +} +} +let environmentVariableRequest = new EnvironmentVariableRequest("theia_Test"); +let value = await Xrm.WebApi.online.execute(environmentVariableRequest) + .then(function (response) { + if (response.ok) { + return response.json().catch(() => { + return response; + }); + } + }) + .then((responseBody) => responseBody); +console.log(value); +``` +#### With XrmEx: + +```js +let value2 = await XrmEx.getEnvironmentVariableValue("theia_Test"); +console.log(value2); +``` +**In Conclusion:** The advanced features of the XrmEx library further exemplify its power in simplifying and enhancing the Dynamics 365 development experience. By abstracting away the complexities, developers can focus on the core logic and functionality of their applications. \ No newline at end of file