@xrmforge/devkit 0.7.5 → 0.7.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -65,28 +65,40 @@ export const onLoad = wrapHandler('LM.Account.onLoad', logger, (ctx) => {
65
65
  const form = typedForm<AccountLMFirmaForm>(ctx.getFormContext());
66
66
 
67
67
  // Direct field access - fully typed, IDE autocomplete works
68
- const name = form.name.getValue(); // string | null (non-nullable, field is on form)
68
+ const name = form.name.getValue(); // string | null
69
69
  form.revenue.setValue(150000); // NumberAttribute
70
70
  const parent = form.parentaccountid.getValue(); // LookupValue[] | null
71
71
 
72
- // Control access
73
- form.$control('name').setDisabled(true);
72
+ // addOnChange directly on the proxy (NOT via $context.getAttribute)
73
+ form.name.addOnChange(() => { logger.debug('Name changed'); });
74
+ form.revenue.addOnChange(() => { recalculate(form); });
74
75
 
75
- // Full FormContext for ui, data, tabs, addOnChange
76
+ // Control access via controls proxy (typed from ControlMap, no cast needed)
77
+ form.controls.name.setDisabled(true);
78
+ form.controls.customerid.setEntityTypes([EntityNames.Account]); // LookupControl
79
+ form.controls.revenue.setVisible(false); // NumberControl
80
+
81
+ // Full FormContext for ui, data, tabs
76
82
  form.$context.ui.setFormNotification('OK', FormNotificationLevel.Info, 'id');
77
- form.$context.getAttribute(Fields.Name).addOnChange(() => { ... });
78
83
  });
79
84
  ```
80
85
 
81
- **When to use `form.$context.getAttribute(Fields.X)` instead of `form.fieldname`:**
82
- - `addOnChange()`, `removeOnChange()` (event registration on the attribute)
86
+ **Use `form.fieldname` (the typedForm proxy) for EVERYTHING on the attribute:**
87
+ - `getValue()`, `setValue()` (reading and writing values)
88
+ - `addOnChange()`, `removeOnChange()` (event registration)
83
89
  - `setRequiredLevel()`, `setSubmitMode()` (attribute-level settings)
84
- - `getControl()` with typed control access (use `form.$control(Fields.X)`)
90
+ - Any attribute method: the proxy returns the full typed Attribute object
85
91
 
86
- **When to use `form.fieldname` (the typedForm proxy):**
87
- - `getValue()`, `setValue()` (reading and writing values)
88
- - `addOnChange()` (event registration directly on the attribute)
89
- - Any read-only access to field values
92
+ **Use `form.controls.fieldname` for control-level operations:**
93
+ - `setDisabled()`, `setVisible()`, `setLabel()`
94
+ - `addPreSearch()` (on LookupControl)
95
+ - `setNotification()`, `clearNotification()`
96
+
97
+ **Use `form.$context` ONLY for FormContext-level operations:**
98
+ - `form.$context.ui` (setFormNotification, tabs, close)
99
+ - `form.$context.data` (save, entity, process)
100
+ - `form.$context.ui.getFormType()`
101
+ - NOT for getAttribute (use the proxy instead)
90
102
 
91
103
  **When to use `form.$unsafe(EntityFields.X)` (off-form fields):**
92
104
 
@@ -367,6 +379,7 @@ Xrm.Navigation.openForm({ entityName: EntityNames.Account, entityId: id }); //
367
379
  - Never unlokalized UI strings (use `pickLang()` from constants.ts)
368
380
  - Never build your own getValue/setFieldValue/setDisabled/addOnChange helpers (use `typedForm` + native Xrm API)
369
381
  - Never `import ... from '@xrmforge/typegen'` in browser code (use `@xrmforge/helpers`)
382
+ - Never `as Xrm.Controls.LookupControl` or similar control casts (`form.controls.fieldname` returns the typed control from ControlMap)
370
383
  - Never `as any` without eslint-disable comment explaining why
371
384
  - Never untyped `catch (error)` (always `catch (error: unknown)`)
372
385
 
@@ -546,7 +559,7 @@ each attribute to its control. `mock.getControl(Fields.Name)` works out of the b
546
559
  | Legacy Pattern | XrmForge Replacement |
547
560
  |---|---|
548
561
  | `getAttribute("name")` | `form.name` (via typedForm) |
549
- | `getControl("name")` | `form.$control(Fields.Name)` |
562
+ | `getControl("name")` | `form.controls.name` |
550
563
  | `Xrm.Page.getAttribute(...)` | `form.fieldname` (via typedForm) |
551
564
  | `var formContext` (global) | `const form = typedForm<MyForm>(ctx.getFormContext())` |
552
565
  | `function form_OnLoad(ctx)` | `export const onLoad = wrapHandler(...)` |
@@ -568,11 +581,11 @@ Never recreate them. Use the typed API directly.
568
581
  |---|---|
569
582
  | `GetValue(fieldName)` | `form.fieldname.getValue()` (typed via typedForm) |
570
583
  | `SetValue(fieldName, value)` | `form.fieldname.setValue(value)` (typed via typedForm) |
571
- | `SetDisabled(attributeName, disabled)` | `form.$control(Fields.X).setDisabled(disabled)` |
572
- | `SetVisible(attributeName, visible)` | `form.$control(Fields.X).setVisible(visible)` |
584
+ | `SetDisabled(attributeName, disabled)` | `form.controls.fieldname.setDisabled(disabled)` |
585
+ | `SetVisible(attributeName, visible)` | `form.controls.fieldname.setVisible(visible)` |
573
586
  | `SetRequiredLevel(attributeName, level)` | `form.$context.getAttribute(Fields.X).setRequiredLevel(RequiredLevel.Required)` |
574
587
  | `AddOnChange(attributeName, callback)` | `form.$context.getAttribute(Fields.X).addOnChange(cb)` |
575
- | `AddPreSearch(controlName, callback)` | `(form.$control(Fields.X) as Xrm.Controls.LookupControl).addPreSearch(cb)` |
588
+ | `AddPreSearch(controlName, callback)` | `form.controls.fieldname.addPreSearch(cb)` (typed as LookupControl from ControlMap) |
576
589
  | `GetLookupValueId(fieldName)` | `formLookupId(form.fieldname)` |
577
590
  | `SetLookupValue(field, id, type, name)` | `form.fieldname.setValue([{ id, entityType, name }])` |
578
591
  | `GetId()` | `form.$context.data.entity.getId()` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xrmforge/devkit",
3
- "version": "0.7.5",
3
+ "version": "0.7.6",
4
4
  "description": "Build orchestration and project tooling for Dynamics 365 WebResources",
5
5
  "keywords": [
6
6
  "dynamics-365",