angular/components · error · Error

A MatDatepicker can only be associated with a single actions

Error message

A MatDatepicker can only be associated with a single actions row.

What it means

registerActions() enforces that a datepicker has at most one mat-datepicker-actions row. If registerActions is called while an actions portal is already assigned, Material throws this dev-mode error.

Source

Thrown at src/material/datepicker/datepicker-base.ts:626

   * @returns Selection model that the input should hook itself up to.
   */
  registerInput(input: C): MatDateSelectionModel<S, D> {
    if (this.datepickerInput && (typeof ngDevMode === 'undefined' || ngDevMode)) {
      throw Error('A MatDatepicker can only be associated with a single input.');
    }
    this._inputStateChanges.unsubscribe();
    this.datepickerInput = input;
    this._inputStateChanges = input.stateChanges.subscribe(() => this.stateChanges.next(undefined));
    return this._model;
  }

  /**
   * Registers a portal containing action buttons with the datepicker.
   * @param portal Portal to be registered.
   */
  registerActions(portal: TemplatePortal): void {
    if (this._actionsPortal && (typeof ngDevMode === 'undefined' || ngDevMode)) {
      throw Error('A MatDatepicker can only be associated with a single actions row.');
    }
    this._actionsPortal = portal;
    this._componentRef?.instance._assignActions(portal, true);
  }

  /**
   * Removes a portal containing action buttons from the datepicker.
   * @param portal Portal to be removed.
   */
  removeActions(portal: TemplatePortal): void {
    if (portal === this._actionsPortal) {
      this._actionsPortal = null;
      this._componentRef?.instance._assignActions(null, true);
    }
  }

  /** Open the calendar. */
  open(): void {

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Keep exactly one <mat-datepicker-actions> inside the datepicker.
  2. Before registering a new portal programmatically, clear or replace the existing _actionsPortal.
  3. Restructure shared datepicker templates so actions are defined once.

Example fix

// before
<mat-datepicker #picker>
  <mat-datepicker-actions><button mat-button>OK</button></mat-datepicker-actions>
  <mat-datepicker-actions><button mat-button>CANCEL</button></mat-datepicker-actions>
</mat-datepicker>

// after
<mat-datepicker #picker>
  <mat-datepicker-actions><button mat-button>OK</button></mat-datepicker-actions>
</mat-datepicker>
Defensive patterns

Strategy: validation

Validate before calling

// Assert exactly one actions row per datepicker in shared templates
function countActions(dp: HTMLElement): number {
  return dp.querySelectorAll('mat-datepicker-actions').length;
}

Prevention

When it happens

Trigger: Declaring <mat-datepicker-actions> twice within one <mat-datepicker>; dynamically attaching an actions portal via registerActions() while one is already registered without unregistering.

Common situations: Duplicating the actions block during copy-paste; programmatic code calling registerActions on each open/creation cycle without clearing the previous portal.

Related errors


AI-assisted analysis of angular/components@0411926e7d (2026-08-31). Data as JSON: /api/errors/68804e93919f5972. Report an issue: GitHub.