northwind-orders-angular — Northwind Orders (Angular)

An Angular port of northwind-orders-js — feature- identical (public Northwind OData V4 endpoint, ODataDataManager, server-side free-text search, toolbar, order detail panel, employee-photo decoding, 8 themes, EN/IT i18n, resizable container, Excel export, multi-selection), all TypeScript. The northwind-orders-angular ↔ northwind-orders-js relationship is the same as github-repos-react ↔ github-repos-js: a framework port of a proven plain-JS app, demonstrating that the zero-dependency components drop into a framework app consumed as-is via classic script tags.

Built with the current stable Angular CLI major (see package.json / package-lock.json): standalone components, signals, zoneless change detection, no NgModules.

The Angular wrapper layer

What it shows (beyond the wrapper layer)

Resizing the grid

The grid sits in a src/vanilla-resize-box/ (aria-label="Resizable orders grid"). Drag the corner handle to resize it — resizing is pointer-driven, with no keyboard path.

The handle carries role="separator" and takes its accessible name from the host's aria-label — here "Resizable orders grid — resize handle" — but is not focusable, so it adds no tab stop to the page. This app's markup needs nothing beyond the aria-label it already carries.

Endpoint

https://services.odata.org/V4/Northwind/Northwind.svc/Orders
    ?$expand=Order_Details($expand=Product),Employee,Customer,Shipper

Total count is fetched from https://services.odata.org/V4/Northwind/Northwind.svc/Orders/$count with the same $filter, so the toolbar status reflects the filtered total. The grid connects directly to services.odata.org from the browser; no backend is required.

Toolbar

Same shape as northwind-orders-js: the empty template exposes the search item plus the standard auto-fit / reset / clear-filters / reload commands (dispatched straight to the grid, no host wiring); selecting rows swaps to the selected template, which adds export-to-Excel, a custom view command (opens the order detail panel, disabled-when="!hasSingleSelection") routed through the directive's command output, and a clear-selection button. The row-count line is the autonomous <vn-grid-toolbar-status>; transient fetch errors go through the host-driven <vn-grid-toolbar-status-message>. Only exportToExcel is overridden (registerCommand) for the app's file naming and device-aware headersOnly (theme-matched Excel styling is automatic); the override returns the export's promise, so the toolbar handles its outcome (a cancelled export is not an error).

Columns

Identical to northwind-orders-js's 24-column set (see northwind-orders-js's README), including the custom cell renderers: Employee (photo + full name), Emp. Location ("City, Country"), Order Total (Σ UnitPrice × Qty × (1 − Discount), currency-formatted), and Order Details (first 3 line items + "+N more…", hard-clipped to the 70 px row height).

Run

npm install       # first time only
npm start         # syncs vendor/ then serves on http://localhost:4200/

Manual verification checklist:

  1. Grid loads the first Northwind page (100 rows) and infinite-scrolls in 100-row pages; the status line shows "Loaded N/total".
  2. Server-side sort round-trips (restarts at page 0 with $orderby); column filters and toolbar search build $filter server-side; the search term survives a page reload.
  3. Toolbar: status counts, search, auto-fit, reset, clear-filters (enabled only with filter/sort), reload, export (selected scope, theme-styled file), view (single selection only), clear selection.
  4. Row double-click opens the order detail panel (employee photo, shipping, dates, line items); theme switch is live across all 8 themes with the Carbon themes swapping the search box to its expandable variant; EN/IT toggle reloads localized.
  5. npm run build output works when served from a subdirectory (relative baseHref), and node build.js (repo root) integrates it into dist/ with shared component paths.

Build

npm run build     # syncs vendor/ then ng build → dist/northwind-orders-angular/browser/

ng build type-checks the whole app (templates included, strictTemplates). The repo-level node build.js delegates to this build, copies the output to dist/samples/northwind-orders-angular/, rewrites the vendor/ script paths to the shared ../../vanilla-components/latest/ folder, minifies the public CSS, and drops the copied vendor/ folder — the same post-process contract wikipedia-pages-vue and github-repos-react get.

Project layout

northwind-orders-angular/
├── angular.json                    # vendor assets mapping; baseHref "./"; no bundled styles
├── package.json                    # @angular/* only — no other runtime deps
├── scripts/sync-vendor.mjs         # copies the 3 component sources → vendor/ (prestart/prebuild)
├── public/
│   ├── styles.css                  # northwind-orders-js's stylesheet, verbatim
│   └── themes/app-*.css            # the 8 app themes + TEMPLATE, verbatim from northwind-orders-js
├── src/
│   ├── index.html                  # favicon ("NOA" badge), overlay boot script, vendor script tags
│   ├── main.ts                     # await VanillaGridReady → bootstrapApplication (zoneless)
│   ├── types/
│   │   ├── global.d.ts             # triple-slash refs to the 3 component .d.ts files
│   │   └── order.ts                # NorthwindOrder row interfaces (expanded navigation props)
│   └── app/
│       ├── app.component.ts|html   # shell: header, theme/language selectors, tab, overlay handoff
│       ├── app.config.ts           # provideZonelessChangeDetection()
│       ├── vanilla/
│       │   ├── vn-grid.directive.ts
│       │   └── vn-grid-toolbar.directive.ts
│       ├── services/
│       │   ├── i18n.service.ts     # signals port of northwind-orders-js's modules/i18n.js (incl. filter-panel bundle)
│       │   └── theme.service.ts    # live theme swap + Carbon expandable-search toggle
│       ├── utils/
│       │   └── employee-photo.ts   # BMP/OLE decode + Lanczos-3 resample (port of northwind-orders-js's module)
│       └── components/
│           ├── orders-tab.component.ts|html   # toolbar + resize-box + grid + columns + wiring
│           ├── order-detail-panel.component.ts|html
│           └── theme-switch-overlay.component.ts
└── README.md

Behavior notes (ported 1:1 from northwind-orders-js)