1.11Common pitfalls

A checklist of mistakes that are easy to make when building against the framework:

  • Touching the framework before OnLoad fires. Any call to Framework.Ask, Framework.Instruments, SendOrder, etc. before the framework has called your OnLoad will fail silently or throw. Put all initialisation inside OnLoad. (§1.6.3)
  • Dispatching messages with switch, else if, or direct .type access. A single message can carry multiple update types at once (e.g. a price tick and an order change in the same message). Always use Msg.is(type) with separate if blocks. Any control flow that matches at most one branch — switch/case, else if, a ternary on .type — will silently drop every update whose type happens to come after an earlier match. (§4.1)
  • Using private settings when category settings are what you want.SavePrivateSettings silently no-ops in floating windows, pop-up dialogs, scripts, and UDIXes. If you're not sure your widget will always be loaded into the page container, use SaveCategorySettings instead — it works everywhere. (§3.6.1, §3.6.2)
  • Calling SaveCategorySettings before LoadCategorySettings. The load call registers your widget's settings ID; saves before that are rejected. Always load first, even if you expect an empty result. (§3.6.2). Note that SaveCategorySettings() does NOT take an ID, because the ID is provided by the earlier call to LoadCategorySettings().
  • Placing interactive elements at the widget's top inline-end corner. The platform overlays close/action icons there — top-right in LTR languages, top-left in RTL. Reserve space using padding-inline-end: var(--widget-chrome-inset-horizontal, 40px) on any top-edge element. Never use padding-right: it will break in Arabic/Hebrew. (§6.2.2)
  • Hard-coding colours instead of using CSS variables.Hard-coding colours instead of using CSS variables. The user can switch between dark, light, and blue themes at runtime without a restart. Hard-coded colours will look wrong in at least one theme. Use --clr-text, --clr-border1, --clr-profit, --clr-loss, etc. — see §6.1.5 for the full list.
  • Assuming HTTP endpoints will work. MyTrader is served over HTTPS, so your widget can only call HTTPS endpoints. Also, third-party services need to send CORS headers — for RSS feeds, proxy through api.rss2json.com or similar. (§1.7.1)
  • Using Framework.SaveCategorySettings as a messaging bus. It is persistent storage, not a message channel. If you only need transient communication between widgets, use the mechanisms in §3.10. (§3.6.2)
  • Assuming scripts and UDIXes have access to widget-only APIs. Dialog rendering, private settings, and UI theming only apply to widgets. Scripts and UDIXes have no UI of their own. (§1.6, §3.6.1, §2.14)
  • Treating Dictionary iterators like array iterators. In a Dictionary such as FXB.Instruments, forEach() iterates with (key, object), not just (object).
  • Attempting to use localStorage or indexedDB in widgets. Widgets are sandboxed, for security reasons, and do not have access to these features. Use the platform's own settings and state storage instead.