
Security News
AGENTS.md Gains Traction as an Open Format for AI Coding Agents
AGENTS.md is a fast-growing open format giving AI coding agents a shared, predictable way to understand project setup, style, and workflows.
@sguez/d365-form-helpers
Advanced tools
Minimal TypeScript helpers that wrap Dynamics 365 / Power Apps client-side `formContext` APIs with typed, ergonomic utilities for form scripting. This repository contains the exact code you provided and concise, copy‑paste examples for every public functi
Minimal TypeScript helpers that wrap Dynamics 365 / Power Apps client-side formContext
APIs with typed, ergonomic utilities for form scripting. This repository contains the exact code you provided and concise, copy‑paste examples for every public function.
Install the package in your project directory with:
npm install @sguez/d365-form-helpers
It is recommended to set the following in your tsconfig.json
:
{
"compilerOptions": {
"moduleResolution": "NodeNext",
"module": "NodeNext"
}
}
Make Dynamics client scripting:
Provider.from(context)
— detects context type and returns either FormContext
or PrimaryControl
.
FormContext
— extends PrimaryControl
and additionally exposes event-specific helpers bound to the provided EventContext
(getDepth, getEventSource, getSharedVariable, setSharedVariable, getContext).
PrimaryControl
— main helper wrapping Xrm.FormContext
with convenient methods:
getAttribute
, getControl
, getTab
, getSection
, getAttributeValue
setAttributeValue
, setRequiredLevel
, setOptional
, setRecommended
, setMandatory
, setVisible
, setDisabled
addOnLoad
, addOnSave
, addOnChange
, addTabStateChange
, addPreSearch
, addSubGridOnLoad
, addOnReadyStateComplete
, addOnOutputChange
, addOnResultOpened
, addOnSelection
, addOnPostSearch
.TabControl
— wrapper for a single tab providing getSection
, label methods, visibility and focus helpers.
CheckTypes
— runtime type guards for Xrm objects (attributes, controls, tabs, grids, iframes, kb search controls, etc.).
Provider.from(executionContext)
because it directly returns an exploitable formContext
without worrying about the type of the source object.All examples assume
@types/xrm
is installed as a dev dependency for editor support.
Provider.from
— automatic context detectionimport Provider from "@sguez/d365-form-helpers/Provider";
// In an onLoad handler
function onLoad(executionContext: Xrm.Events.EventContext) {
const formContext: FormContext = Provider.from(executionContext); // returns FormContext
formContext.setVisible("mobilephone", false);
console.log("depth:", formContext.getDepth());
}
// In a ribbon action (primaryControl provided)
function ribbonAction(primaryControl: Xrm.FormContext) {
const formContext: PrimaryControl = Provider.from(primaryControl); // returns PrimaryControl
formContext.setDisabled("name", true);
}
PrimaryControl
— creation and getters/settersimport PrimaryControl from "@sguez/d365-form-helpers/PrimaryControl";
function example(executionContext: Xrm.Events.EventContext) {
const formContext: PrimaryControl = new PrimaryControl(executionContext.getFormContext()); // or use Provider.from(executionContext)
// Get attribute, control, tab, section
const attribute = formContext.getAttribute("emailaddress1");
const control = formContext.getControl("mobilephone");
const tab = formContext.getTab("Summary");
const section = formContext.getSection("AddressSection");
// Read values
const emailAddress = formContext.getAttributeValue("emailaddress1");
const values = formContext.getAttributeValue(attribute => attribute.getName().startsWith("_custom_"));
// Set values
formContext.setAttributeValue("firstname", "John");
formContext.setAttributeValue(["firstname", "lastname"], "REDACTED");
// Requirement level
formContext.setRequiredLevel("emailaddress1", "required");
formContext.setOptional("middlename");
formContext.setRecommended("nickname");
formContext.setMandatory(["firstname", "lastname"]);
// Visibility / disabled
formContext.setVisible("mobilephone", false);
formContext.setVisible(["mobilephone","telephone1"], true);
formContext.setVisible(c => c.getName().startsWith("addr_"), false);
formContext.setDisabled("mobilephone", true);
formContext.setDisabled(["mobilephone","telephone1"], false);
}
PrimaryControl
— event helpers (examples for each method)function registerHandlers(formContext: Xrm.FormContext) {
const formContext: PrimaryControl = new PrimaryControl(formContext); // or use Provider.from(formContext)
// Form and data events
formContext.addOnLoad(ctx => console.log('form loaded'));
formContext.addOnDataLoad(ctx => console.log('data loaded'));
formContext.addLoaded(ctx => console.log('ui loaded'));
formContext.addOnSave(ctx => console.log('on save'));
formContext.addOnPostSave(ctx => console.log('post save'));
// Process events
formContext.addOnPreProcessStatusChange(ctx => console.log('pre process status'));
formContext.addOnProcessStatusChange(ctx => console.log('process status'));
formContext.addOnPreStageChange(ctx => console.log('pre stage change'));
formContext.addOnStageChange(ctx => console.log('stage change'));
formContext.addOnStageSelected(ctx => console.log('stage selected'));
// Attribute change
formContext.addOnChange('emailaddress1', ev => console.log('email changed'));
formContext.addOnChange(['firstname','lastname'], ev => console.log('name changed'));
formContext.addOnChange(a => a.getName().startsWith('_custom_'), ev => console.log('custom changed'));
// Tab state
formContext.addTabStateChange('Summary', ev => console.log('tab state changed'));
// Lookup events
formContext.addOnLookupTagClick('parentaccountid', ev => console.log('lookup tag clicked'));
formContext.addPreSearch('parentaccountid', () => console.log('presearch'));
// Grid / subgrid
formContext.addSubGridOnLoad('ContactsSubgrid', ctx => console.log('subgrid loaded'));
formContext.addSubGridOnRecordSelect('ContactsSubgrid', ctx => console.log('record selected'));
// Iframe
formContext.addOnReadyStateComplete('webresource_iframe', ctx => console.log('iframe ready'));
// Standard control
formContext.addOnOutputChange('someControl', ctx => console.log('output changed'));
// KnowledgeBase Search control
formContext.addOnResultOpened('kbSearch', ctx => console.log('result opened'));
formContext.addOnSelection('kbSearch', ctx => console.log('kb selection'));
formContext.addOnPostSearch('kbSearch', ctx => console.log('post search'));
}
FormContext
— event-aware wrapperimport { Provider } from "@sguez/d365-form-helpers";
function onChange(executionContext: Xrm.Events.EventContext) {
const formContext: FormContext = Provider.from(executionContext); // returns FormContext
const source = formContext.getEventSource();
const depth = formContext.getDepth();
formContext.setSharedVariable('myKey', { started: true });
const shared = formContext.getSharedVariable('myKey');
}
TabControl
usageconst tab = form.getTab('Summary');
if (tab) {
const section = tab.getSection('AddressSection');
section?.setVisible(false);
tab.setLabel('Main summary');
tab.setFocus();
}
CheckTypes
— type guard examplesimport { isLookupControl, isGridControl, isAttribute } from "@sguez/d365-form-helpers";
const control = formContext.getControl('parentaccountid'); // control: Xrm.Controls.Control
if (isLookupControl(control)) { // control: Xrm.Controls.LookupControl
control.addOnLookupTagClick(() => console.log('tag clicked'));
}
const grid = formContext.getControl('contacts'); // grid: Xrm.Controls.Control
if (isGridControl(grid)) { // control: Xrm.Controls.GridControl
grid.addOnLoad(ctx => console.log('grid loaded'));
}
const attribute = formContext.getAttribute('emailaddress1');
if (isAttribute(attribute)) {
console.log('attribute type', attribute.getAttributeType());
}
FAQs
Minimal TypeScript helpers that wrap Dynamics 365 / Power Apps client-side `formContext` APIs with typed, ergonomic utilities for form scripting. This repository contains the exact code you provided and concise, copy‑paste examples for every public functi
The npm package @sguez/d365-form-helpers receives a total of 6 weekly downloads. As such, @sguez/d365-form-helpers popularity was classified as not popular.
We found that @sguez/d365-form-helpers demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
AGENTS.md is a fast-growing open format giving AI coding agents a shared, predictable way to understand project setup, style, and workflows.
Security News
/Research
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
Security News
This episode explores the hard problem of reachability analysis, from static analysis limits to handling dynamic languages and massive dependency trees.