Components
Angular
Add bill submission and lifecycle management, then compose dashboards, reporting, and practice settings with standalone Angular components.
Add billing to your application
Follow the components quickstart and select Angular for installation, a session endpoint, a create-bill page, routing, and a dashboard. The flow is the same as React: review and submit a bill, save its ID on your report, and reopen its lifecycle view.
Component catalog
This reference targets @mindbill/angular@0.19.0. The server API and browser-session contract are shared with React; the available UI exports differ.
Submit a billMindBillBillSubmissionComponentAngular equivalent of BillSubmissionForm; emits (submitted).Open a submitted billMindBillBillLifecycleComponentConnected bill view; pass billId and sessionEndpoint.Dashboard and reportsMindBillBillingDashboardComponentPass authorized bills and handle navigation. Angular does not export ConnectedBillingWorkspace.Save practice settingsMindBillOrganizationOnboardingComponentUse variant="settings" for editing saved practice details.Custom lifecycle UIMindBillLifecycleStoreSignal-based state and actions for your Angular templates.Email notification preferencesHost UI + notification APIThe React notification-settings components have no Angular export in this release.Individual React form sections, connected search/productivity/payment-review surfaces, and courtesy-copy recipient controls are not interchangeable Angular imports. Use the supported components below or build an Angular view over the shared API.
Setup
npm install @mindbill/angular@0.19.0All Angular exports are standalone components. Import only the surfaces your product needs. The previews on this page are the real Angular components, rendered live from the published bundle. Angular 18–21 and RxJS 7.8 or 8 satisfy this release’s peer dependencies. The previews use a separately deployed Angular bundle; the copyable examples below target the published package.
Session endpoint
Keep the permanent API key on your server. This is the only MindBill-specific server route required by the embedded components: authenticate the current user and mint a short-lived, exact-origin browser token.
Use the server route recipe for your backend. It must authenticate the user, select their organization credential, and enforce permissions before minting a session. Configure APP_ORIGIN as the Angular app’s exact origin, not the API server’s URL.
Set MINDBILL_API_KEY in the backend environment and restart that server after changing it. Do not put the key in Angular environment.ts, browser code, or a public environment variable. Use the shared session troubleshooting steps if the route returns “Billing session unavailable.” For local development, proxy /api to your backend; the session’s allowed origin must still be the Angular app’s origin.
Complete case workflow
Start with editable fields, then prefill them from your report and supply the finalized PDFs. Switch to the connected lifecycle component after submission. The browser submits directly to MindBill; your server does not proxy or transform the bill payload.
import { Component } from "@angular/core";
import {
MindBillBillLifecycleComponent, MindBillBillSubmissionComponent,
type BrowserBillCreateInput,
} from "@mindbill/angular";
@Component({
selector: "app-new-bill",
standalone: true,
imports: [MindBillBillLifecycleComponent, MindBillBillSubmissionComponent],
template: `
@if (billId) {
<mindbill-bill-lifecycle [billId]="billId"
sessionEndpoint="/api/mindbill/session" />
} @else {
<mindbill-bill-submission [initialBill]="initialBill"
sessionEndpoint="/api/mindbill/session"
(submitted)="handleSubmitted($event.bill.id)" />
}
`,
})
export class NewBillComponent {
// TODO: Load the current report from your backend before mounting.
report = { id: "report_demo_001", mindbillBillId: null };
billId: string | null = this.report.mindbillBillId;
handleSubmitted(billId: string) {
this.billId = billId;
// TODO: Save billId on this report through your backend.
// PATCH /api/reports/:id with { mindbillBillId: billId }
}
initialBill: BrowserBillCreateInput = {
externalId: this.report.id,
patient: {
firstName: "", lastName: "", dateOfBirth: "",
address: { line1: "", city: "", state: "CA", postalCode: "" },
},
claim: {
claimNumber: "", employer: "", dateOfInjury: "",
claimsAdministrator: { id: "", name: "" },
},
service: { date: "" },
billingProvider: {
name: "", taxId: "", npi: "", phone: "",
address: { line1: "", city: "", state: "CA", postalCode: "" },
},
renderingProvider: { name: "", npi: "", taxonomy: "" },
serviceLocation: {
address: { line1: "", city: "", state: "CA", postalCode: "" },
placeOfServiceCode: "11",
},
diagnoses: [], serviceLines: [],
};
}Use a stable externalId from your case or report. Persist the returned billId for fast lookup, or reconcile it later through the external ID and signed events.
The persistence recipe saves the returned ID through your backend. If saving that link fails, the bill has already been submitted: recover it using externalId rather than submitting again. An external ID is a lookup key, not a uniqueness guarantee.
Complete submission form
MindBillBillSubmissionComponent includes the complete patient, injury, payer, provider, service-location, diagnosis, service-line, fee schedule, and attachment workflow. It marks required fields, scrolls to the first error, resolves ZIP codes, searches claims administrators and ICD-10 codes, validates routing selections, calculates totals, and submits one immutable bill snapshot.
mindbill-bill-submission inputs and outputs
initialBillBrowserBillCreateInputPrefilled patient, claim, provider, diagnosis, and service-line values from your case.attachmentsMindBillSubmissionAttachment[]Documents supplied by your product. locked: true renders an auto-attached, non-removable row — use it for the finalized report and the practice W-9.sessionEndpointstringYour authenticated route that returns { token }. Default /api/mindbill/session.apiBaseUrlstringOverride the MindBill API origin (sandbox proxies, tests).appearanceMindBillAngularAppearancePreset plus per-token overrides.submitter(input) => Promise<BrowserBillSubmissionResult>Optional custom submit hook; omit to submit directly to MindBill.(submitted)BrowserBillSubmissionResultFires once with the immutable billId after atomic submission.(submissionError)ErrorSession or submission failure; show feedback in your application.(billChange)BrowserBillCreateInputEdited form snapshot; avoid logging or persisting sensitive form values.Attach finalized documents
Provide PDF bytes using contentBase64, contentUrl, or loadBlob. A filename alone is not an attachment. Your document endpoint must enforce access to the report. Omit attachments to let users choose files in the form.
import type { MindBillSubmissionAttachment } from "@mindbill/angular";
// Supply these as [attachments] on mindbill-bill-submission.
// This is your existing authenticated document endpoint.
const attachments: MindBillSubmissionAttachment[] = [{
filename: "final-report.pdf",
documentType: "final_report",
locked: true,
loadBlob: async () => {
const response = await fetch("/api/documents/report_demo_001", {
credentials: "same-origin", cache: "no-store",
});
if (!response.ok) throw new Error("Could not load finalized report");
return response.blob();
},
}];import { Component } from "@angular/core";
import {
MindBillBillLifecycleComponent, MindBillBillSubmissionComponent,
type BrowserBillCreateInput,
} from "@mindbill/angular";
@Component({
selector: "app-new-bill",
standalone: true,
imports: [MindBillBillLifecycleComponent, MindBillBillSubmissionComponent],
template: `
@if (billId) {
<mindbill-bill-lifecycle [billId]="billId"
sessionEndpoint="/api/mindbill/session" />
} @else {
<mindbill-bill-submission [initialBill]="initialBill"
sessionEndpoint="/api/mindbill/session"
(submitted)="handleSubmitted($event.bill.id)" />
}
`,
})
export class NewBillComponent {
// TODO: Load the current report from your backend before mounting.
report = { id: "report_demo_001", mindbillBillId: null };
billId: string | null = this.report.mindbillBillId;
handleSubmitted(billId: string) {
this.billId = billId;
// TODO: Save billId on this report through your backend.
// PATCH /api/reports/:id with { mindbillBillId: billId }
}
initialBill: BrowserBillCreateInput = {
externalId: this.report.id,
patient: {
firstName: "", lastName: "", dateOfBirth: "",
address: { line1: "", city: "", state: "CA", postalCode: "" },
},
claim: {
claimNumber: "", employer: "", dateOfInjury: "",
claimsAdministrator: { id: "", name: "" },
},
service: { date: "" },
billingProvider: {
name: "", taxId: "", npi: "", phone: "",
address: { line1: "", city: "", state: "CA", postalCode: "" },
},
renderingProvider: { name: "", npi: "", taxonomy: "" },
serviceLocation: {
address: { line1: "", city: "", state: "CA", postalCode: "" },
placeOfServiceCode: "11",
},
diagnoses: [], serviceLines: [],
};
}Loading the live Angular component…
Field requirements and payer mappings come from MindBill, not host-app validation. See The bill resource for the complete required/optional contract and Create and submit a bill for cURL and response examples.
Load the saved bill ID with the case and persist $event.bill.id in your host application when submission succeeds. Local component state alone is lost on refresh. Pass only the finalized report and supporting PDFs the user has selected.
Lifecycle component
MindBillBillLifecycleComponent loads the submitted snapshot, status, EORs, documents, payments, and history. Its action flows include corrections, second review, duplicate copies, payment posting, status reporting, and closure when eligible. MindBillLifecycleStore exposes the same connected state as an injectable service for fully custom layouts.
It receives only a submitted billId and a session, not editable initial bill data. For access to one bill, use an authenticated route such as /api/mindbill/bills/:billId/session that checks the user’s bill access and mints resource: { billId } with the required read/action permissions. See the session recipe.
mindbill-bill-lifecycle inputs and outputs
billIdstringThe submitted bill to track. Required.sessionEndpointstringYour authenticated session route. Default /api/mindbill/session.getSession() => Promise<BillLifecycleSession>Programmatic alternative to sessionEndpoint.apiBaseUrlstringOverride the MindBill API origin.refreshIntervalnumberMilliseconds between automatic refreshes. Default 60000.appearanceMindBillAngularAppearancePreset plus per-token overrides.(billingError)ErrorSession or fetch failures, after the built-in retry surface.Operations components
Organization-level surfaces can be embedded together or independently. The dashboard includes monthly submitted and closed totals, outstanding balance, aging buckets, search, status filters, and bill drill-down. The report component exports the normalized bill list, and the management button opens a short-lived SSO session in MindBill.
import { Component, EventEmitter, Input, Output } from "@angular/core";
import {
MindBillBillingDashboardComponent,
MindBillBillingReportComponent,
MindBillBillingManagementButtonComponent,
type MindBillDashboardBill, type MindBillAngularAppearance,
} from "@mindbill/angular";
@Component({
standalone: true,
imports: [
MindBillBillingDashboardComponent,
MindBillBillingReportComponent,
MindBillBillingManagementButtonComponent,
],
template: `
<mindbill-billing-dashboard
[bills]="bills"
[appearance]="appearance"
(billSelected)="billSelected.emit($event)"
(createBill)="createBill.emit()"
/>
<mindbill-billing-report [bills]="bills" [appearance]="appearance" />
<mindbill-billing-management-button
sessionEndpoint="/api/mindbill/management-session"
[appearance]="appearance"
label="View details in MindBill"
/>
`,
})
export class BillingOperationsComponent {
@Output() createBill = new EventEmitter<void>();
@Input({ required: true }) bills: MindBillDashboardBill[] = [];
@Output() billSelected = new EventEmitter<MindBillDashboardBill>();
appearance: MindBillAngularAppearance = { preset: "clinical-blue" };
}import { Component, EventEmitter, Input, Output } from "@angular/core";
import { MindBillBillingDashboardComponent, type MindBillDashboardBill } from "@mindbill/angular";
@Component({
selector: "app-billing-dashboard",
standalone: true,
imports: [MindBillBillingDashboardComponent],
template: `
<mindbill-billing-dashboard
[bills]="bills"
[appearance]="{ preset: 'clinical-blue' }"
(billSelected)="billSelected.emit($event)"
(createBill)="createBill.emit()"
/>
`,
})
export class BillingDashboardComponent {
@Input({ required: true }) bills: MindBillDashboardBill[] = [];
@Output() billSelected = new EventEmitter<MindBillDashboardBill>();
@Output() createBill = new EventEmitter<void>();
}Loading the live Angular component…
For a working page that loads rows, handles errors, and opens bill details, copy the Angular dashboard recipe. These components do not fetch the bills themselves. Totals cover the supplied rows only: load every relevant page for a complete summary, or build a paginated view using the API’s totals.
All operations components consume the same normalized MindBillDashboardBill summaries — id, patient, claim, payer, state, submittedAt or agingDays, and the three money fields — so the same authorized data load can feed several surfaces. Bill-task dashboards use their own task response rather than this bill-summary array. summarizeMindBillDashboard, buildMindBillReportRows, and buildMindBillReportCsv are exported for custom layouts and reporting. For CSV, pass buildMindBillReportRows(bills, "payer") into buildMindBillReportCsv.
Status × aging matrix
MindBillStatusAgingMatrixComponent is the management view billing teams expect from legacy tools: one row per lifecycle status, one column per 0–30 / 31–60 / 61–90 / 91+ aging bucket, clickable counts with outstanding balances, and row, column, and grand totals. Every emitted cell carries the exact bills behind its count, so a drill-down never needs a second query.
import { Component, EventEmitter, Input, Output } from "@angular/core";
import {
MindBillBillListComponent,
MindBillStatusAgingMatrixComponent,
type MindBillStatusAgingCell, type MindBillDashboardBill, type MindBillAngularAppearance,
} from "@mindbill/angular";
@Component({
standalone: true,
imports: [MindBillStatusAgingMatrixComponent, MindBillBillListComponent],
template: `
<mindbill-status-aging-matrix
[bills]="bills"
[appearance]="appearance"
(cellSelected)="cell = $event"
/>
@if (cell) {
<mindbill-bill-list
[bills]="cell.bills"
[appearance]="appearance"
(billSelected)="billSelected.emit($event)"
/>
}
`,
})
export class BillingMatrixComponent {
cell: MindBillStatusAgingCell | null = null;
@Input({ required: true }) bills: MindBillDashboardBill[] = [];
@Output() billSelected = new EventEmitter<MindBillDashboardBill>();
appearance: MindBillAngularAppearance = { preset: "clinical-blue" };
}import { Component, EventEmitter, Input, Output } from "@angular/core";
import {
MindBillBillListComponent,
MindBillStatusAgingMatrixComponent,
type MindBillStatusAgingCell, type MindBillDashboardBill, type MindBillAngularAppearance,
} from "@mindbill/angular";
@Component({
standalone: true,
imports: [MindBillStatusAgingMatrixComponent, MindBillBillListComponent],
template: `
<mindbill-status-aging-matrix
[bills]="bills"
[appearance]="appearance"
(cellSelected)="cell = $event"
/>
@if (cell) {
<mindbill-bill-list
[bills]="cell.bills"
[appearance]="appearance"
(billSelected)="billSelected.emit($event)"
/>
}
`,
})
export class BillingMatrixComponent {
cell: MindBillStatusAgingCell | null = null;
@Input({ required: true }) bills: MindBillDashboardBill[] = [];
@Output() billSelected = new EventEmitter<MindBillDashboardBill>();
appearance: MindBillAngularAppearance = { preset: "clinical-blue" };
}Loading the live Angular component…
mindbill-status-aging-matrix inputs and outputs
billsMindBillDashboardBill[]The same normalized summaries the dashboard consumes.heading / descriptionstringHeader copy above the grid.stateOrderstring[]Pin your lifecycle-first row order; unknown states append alphabetically.showBalancesbooleanShow outstanding balance under each count. Default true.appearanceMindBillAngularAppearancePreset plus per-token overrides.(cellSelected)MindBillStatusAgingCell{ state, bucket, count, balance, bills } for the clicked cell, including totals cells.buildMindBillStatusAgingMatrix and buildMindBillStatusAgingCsv expose the same aggregation presentation-free for custom grids and exports.
Management button
MindBillBillingManagementButtonComponent is the prebuilt hosted-SSO launcher. It opens a tab synchronously (so popup blockers cooperate), asks your server for a one-time URL, and navigates the tab when the URL arrives.
mindbill-billing-management-button inputs and outputs
sessionEndpointstringYour authenticated route that returns { url }. Default /api/mindbill/management-session.sessionProvider() => Promise<{ url } | string>Programmatic alternative to sessionEndpoint.label / loadingLabelstringButton copy. Defaults: “Billing management” / “Opening billing…”.appearanceMindBillAngularAppearancePreset plus per-token overrides.(opened)stringThe URL that was opened.(failed)unknownSession minting or navigation failures.import { Component } from "@angular/core";
import { MindBillBillingManagementButtonComponent } from "@mindbill/angular";
@Component({
standalone: true,
imports: [MindBillBillingManagementButtonComponent],
template: `
<mindbill-billing-management-button
sessionEndpoint="/api/mindbill/management-session"
[appearance]="{ preset: 'clinical-blue' }"
/>
`,
})
export class BillingManagementComponent {}Loading the live Angular component…
Saved practice settings
import { Component } from "@angular/core";
import { MindBillOrganizationOnboardingComponent } from "@mindbill/angular";
@Component({
selector: "app-billing-settings",
standalone: true,
imports: [MindBillOrganizationOnboardingComponent],
template: `<mindbill-organization-onboarding
variant="settings"
sessionEndpoint="/api/mindbill/settings-session"
/>`,
})
export class BillingSettingsComponent {}Create a separate administrator-authorized /api/mindbill/settings-session route with organization:manage. Keep ordinary bill creators on the billing session; do not grant settings permissions merely to submit a bill.
MindBillOrganizationOnboardingComponent captures the practice identity, pay-to billing provider, locations, and W-9 once — saved straight to your MindBill organization through a browser session minted with the optional organization:manage permission. Your users never visit the MindBill dashboard. Set variant="settings" for the compact edit-after-setup layout; the review step renders MindBill's real onboarding checklist and (completed) fires when billing setup is done.
From Angular 0.18.0, settings and bill submission support EIN/SSN selection and password-style SSN inputs. Blank saved SSN inputs preserve the identifier; use the clear button or enter a replacement to change it on save. To submit from a saved profile, pass billingProvider: { savedProviderId }; SSN corrections and duplicates preserve the original provider with { sourceBillId }. The form keeps either reference until the user explicitly chooses a different manual provider. Angular does not export React’s organizationProfileOptions or accept its profileOptions prop. Load authorized profile choices in your app and assign the chosen provider reference to initialBill.billingProvider. See the bill contract.
sessionEndpointstringYour authenticated session route. The session needs the organization:manage permission.variant"onboarding" | "settings"Stepper for first-run setup, stacked sections for editing. Default onboarding.appearanceMindBillAngularAppearancePreset plus per-token overrides.(saved$)OrganizationProfileDataFires after each section saves.(completed)OrganizationProfileDataFires once when the onboarding checklist is complete.(organizationError)ErrorLoad or save failures.Notification settings
Angular 0.19.0 has no NotificationSettings or NotificationRecipientsSettings component. Build an Angular preferences or recipient-list view against your authenticated host-server adapter using the same notification API contract. Your server owns identity, verified email, practice and bill access, consent records, and the API key.
Support reportDigest (off, daily, or weekly) alongside status alerts and aging reminders. An administrator’s invitation does not enroll a recipient: the email owner must review and confirm it. Personal preference changes need explicit consent; reload the authoritative preferences after saving. Sandbox sends no email.
Custom lifecycle UI
Use MindBillLifecycleStore when you need your own Angular markup. Scope it to the bill component and disconnect on destruction or when switching bills. Unlike React, this release does not export individual status, progress, remittance, payment-ledger, action-bar, or timeline components.
import { Component, Input, OnChanges, OnDestroy, inject } from "@angular/core";
import { MindBillLifecycleStore } from "@mindbill/angular";
@Component({
selector: "app-billing-status",
standalone: true,
providers: [MindBillLifecycleStore], // One store per bill view.
template: `
@if (store.loading()) { <p role="status">Loading bill…</p> }
@if (store.error()) { <p role="alert">Could not load billing status.</p> }
<button type="button" (click)="refresh()" [disabled]="store.loading()">
Refresh status
</button>
<!-- Render your layout from store.data() after checking it is available. -->
`,
})
export class BillingStatusComponent implements OnChanges, OnDestroy {
@Input({ required: true }) billId = "";
readonly store = inject(MindBillLifecycleStore);
ngOnChanges() {
this.store.disconnect();
if (this.billId) this.store.connect({
billId: this.billId,
sessionEndpoint: `/api/mindbill/bills/${encodeURIComponent(this.billId)}/session`,
});
}
async refresh() {
try { await this.store.refresh(); } catch { /* store.error supplies feedback */ }
}
ngOnDestroy() { this.store.disconnect(); }
}The store exposes data(), loading(), error(), and mutating(), plus operations such as postPayment, resubmitBill, submitSecondReview, and closeBill. Render eligible actions from the server’s lifecycle response. For client factories, import from @mindbill/browser; Angular re-exports the lifecycle client type, not every factory.
Exports and utilities
MindBillBillSubmissionComponentmindbill-bill-submissionReview, validate, attach documents, and submit a bill.MindBillBillLifecycleComponentmindbill-bill-lifecycleBill detail, status, EOR, payments, history, and lifecycle actions.MindBillBillingDashboardComponentmindbill-billing-dashboardMonthly metrics, aging, bill search, and drill-down.MindBillStatusAgingMatrixComponentmindbill-status-aging-matrixStatus × aging management grid with drill-down cells and totals.MindBillBillTasksDashboardComponentmindbill-bill-tasks-dashboardTask and aging counts from supplied task data; emits drill-down cells.MindBillBillRejectionNoticeComponentmindbill-bill-rejection-noticeRejection details from the supplied rejection object.MindBillBillAgingSummaryComponentmindbill-bill-aging-summaryClickable outstanding-balance aging buckets.MindBillBillListComponentmindbill-bill-listSearchable, filterable list of bills.MindBillBillingReportComponentmindbill-billing-reportOperational reporting and CSV export.MindBillBillingManagementButtonComponentmindbill-billing-management-buttonPrebuilt SSO launcher for the hosted MindBill workspace.MindBillOrganizationOnboardingComponentmindbill-organization-onboardingPractice identity, locations, and W-9 setup saved straight to MindBill.MindBillLifecycleStoreinjectableConnected lifecycle state, actions, and downloads for custom layouts.Presentation-free utilities: summarizeMindBillDashboard, buildMindBillReportRows, buildMindBillReportCsv, buildMindBillStatusAgingMatrix, buildMindBillStatusAgingCsv, mindBillAgingDays, mindBillAgingBucket, and ensureTrailingProcedureLine.
Use mindBillAngularAppearanceStyle for your own themed markup. Appearance presets include mindbill, orange-bright, and clinical-blue. Every visual token can also be overridden.