Skip to content
Infragistics

What's New in Ignite UI for Angular 22.2

Ignite UI for Angular 22.2 adds IgxVirtualScrollComponent, Angular Signal Forms support in ten form controls, and standard CSS scrollbars. This post covers each change, the theming and button group breaking changes, and the ng update path.

Ignite UI for Angular 22.2.0 shipped on September 30, 2026, and the 22.2.1 patch followed on October 5, 2026. The release adds IgxVirtualScrollComponent, a standalone Angular virtual scroll for long lists with variable item sizes, Angular Signal Forms support through [formField] in ten form controls, and standard CSS scrollbar styling in place of the ::-webkit-scrollbar-* pseudo-elements. Breaking changes land in scrollbar-theme, grid-summary-theme, the button directives and the button group, and ng update migrates the theming arguments and the removed multiSelection input automatically.

The thread through 22.2, and the reason I think its breaking changes are worth taking, is that the library stops maintaining its own versions of things the platform already does. Form controls read their state from Signal Forms, scrollbars use the standard CSS properties, and summary cells take their border width from the grid they sit in. Each move gives up some control, and every section below says where.

Ignite UI for Angular 22.2 at a glance

Ignite UI for Angular is a UI component library by Infragistics for Angular applications, including a high-performance data grid and charting. The table lists every Ignite UI for Angular 22.2 change that needs a decision during an upgrade, with the version that introduced it.

Change Version Type Action on upgrade
IgxVirtualScrollComponent 22.2.0 New component None, opt in
Signal Forms ([formField]) in ten form controls 22.2.0 New feature None
igc-color-picker with ngModel and formControlName 22.2.0 New feature None
Combo, Simple Combo and Excel-style filtering list on IgxVirtualScrollComponent 22.2.0 Internal change Update tests and CSS that target the old list markup
Standard CSS scrollbars 22.2.0 Breaking (theming) ng update, then a visual check
grid-summary-theme border widths removed 22.2.0 Breaking (theming) ng update, then review renamed custom properties
IgxButtonGroupComponent: multiSelection removed, values typed 22.2.0 Breaking ng update for templates, manual for TypeScript
IgxButtonDirective and IgxIconButtonDirective members removed 22.2.0 Breaking Manual
PDF export shading and merged Pivot Grid row dimension cells 22.2.0 Behavioral Review exported reports
Pivot Grid and Tree Grid template directives in standalone arrays 22.2.1 New feature None
GridBaseAPIService and IgxFilteringService deprecations 22.2.1 Deprecation Plan replacements
Tree Grid beginAddRowByIndex and filter() behavior 22.2.1 Behavioral Review calls

IgxVirtualScrollComponent: a new Angular virtual scroll for long lists

IgxVirtualScrollComponent is a new Ignite UI for Angular 22.2 component that renders only the items inside the viewport, plus an over-scan buffer, so the DOM holds a window of rows instead of the whole list. Import it, together with the igxVirtualItem template directive, from igniteui-angular/virtual-scroll.

IgxVirtualScrollComponent covers the cases that usually force a custom solution:

  • Vertical and horizontal orientation, with right-to-left support.
  • Variable item sizes, measured in the DOM. Items that have not been measured yet take the average measured size, so the scrollbar tracks the real content.
  • Recycled item elements: a scroll step updates only the items entering the window, and keyFunction lets an element follow its item when data is reordered.
  • scrollToIndex with scrollIntoView-style alignment (start, center, end, nearest), corrected until it lands on the item.
  • Infinite scrolling through the dataRequest output, and paged data through dataWindow, with a scrollbar that spans the whole collection.
  • Lists larger than the browser’s maximum scroll size.

Example: an infinite activity log in Angular

The scenario I would reach for IgxVirtualScrollComponent first is a log or activity feed: rows have different heights, and data arrives a page at a time. The Angular component below loads a first page, appends pages from dataRequest, keys rows by id, and maps each row’s position onto aria-posinset and aria-setsize so assistive technology still knows where it is in the list.

import { Component, signal } from '@angular/core';
import {
  IgxVirtualScrollComponent,
  IgxVirtualItemDirective,
} from 'igniteui-angular/virtual-scroll';
import type { VirtualScrollDataRequest } from 'igniteui-angular/virtual-scroll';

interface LogEntry {
  id: number;
  message: string;
}

// Stand-in for a paged backend call. Replace with your own data access.
async function fetchEntries(startIndex: number, count: number): Promise<LogEntry[]> {
  return Array.from({ length: count }, (_, i) => ({
    id: startIndex + i,
    message: `Log entry ${startIndex + i}`,
  }));
}

@Component({
  selector: 'app-log-viewer',
  imports: [IgxVirtualScrollComponent, IgxVirtualItemDirective],
  template: `
    <igx-virtual-scroll
      [data]="entries()"
      [keyFunction]="byId"
      (dataRequest)="loadMore($event)"
      style="height: 480px;">
      <ng-template igxVirtualItem let-entry let-i="index" let-count="count">
        <div role="listitem" [attr.aria-posinset]="i + 1" [attr.aria-setsize]="count">
          {{ entry.message }}
        </div>
      </ng-template>
    </igx-virtual-scroll>
  `,
})
export class LogViewerComponent {
  // A signal keeps the view in sync in zoneless and zone-based apps alike.
  entries = signal<LogEntry[]>([]);

  byId = (entry: LogEntry) => entry.id;

  constructor() {
    // dataRequest does not fire for an empty array, so load the first page yourself.
    fetchEntries(0, 50).then(page => this.entries.set(page));
  }

  async loadMore(request: VirtualScrollDataRequest) {
    const page = await fetchEntries(request.startIndex, request.count);
    // data is compared by reference: append into a new array, never push in place.
    this.entries.update(current => [...current, ...page]);
  }
}

The snippet assumes an Angular 22 application with igniteui-angular 22.2 installed and a theme applied; the Ignite UI for Angular setup reference covers both. Two lines carry most of the weight. entries is a signal, so the view updates in zoneless and zone-based applications alike. loadMore assigns a new array, because IgxVirtualScrollComponent compares data by reference and does not react to an in-place push.

Limitations of IgxVirtualScrollComponent

IgxVirtualScrollComponent virtualizes one list of templated items. For tabular data with columns, sorting and filtering, the Angular Data Grid is still the component to use. Check these constraints, all documented in the IgxVirtualScrollComponent README, before adopting it:

  • The host needs a fixed height (vertical) or a fixed width (horizontal). The default styles already set overflow.
  • Items are measured by their border box, so margins accumulate as drift. Use padding on the item, or gap on a wrapper.
  • Recycled elements keep any DOM state that is not bound. A checkbox toggled without [checked] shows up on another item, so bind all item state.
  • dataRequest is not emitted for an empty initial array, and it is not emitted at all while dataWindow is bound.
  • With dataWindow, the engine keeps one size entry per index of totalCount: roughly 17 MB per million items, per the 22.2 IgxVirtualScrollComponent README.
  • Inside a drop-down, dialog or other container that is hidden until it opens, the first render has no viewport to measure, so rows appear on the next frame. Read the rendered rows after layoutComplete resolves.

Combo, Simple Combo and Excel-style filtering now run on IgxVirtualScrollComponent

In Ignite UI for Angular 22.2, IgxComboComponent, IgxSimpleComboComponent and the Excel-style filtering search list virtualize their items with IgxVirtualScrollComponent instead of the igxFor directive. Each row is measured in the DOM once it renders, and the measured size replaces the estimate it started from.

The upgrade risk here sits in test code and CSS overrides, not in application logic. The list markup changed: igx-display-container and the igx-vhelper--vertical scrollbar are replaced by the igx-virtual-scroll host and its igx-virtual-item row wrappers, so end-to-end selectors and style rules that reach into the old elements stop matching. The public virtualizationState and totalItemCount members are unchanged. Only the internal virtualScrollContainer member, marked @hidden @internal, changed type, and the Excel-style filtering search list no longer has a virtDir.

The switch also brings fixes to the Angular Combo and Simple Combo:

  • Remote pages no longer change position before their replacements arrive, and an already loaded initial range is not requested again.
  • A change to a positive totalItemCount refreshes the list without rebinding data.
  • Each combo resolves its selection once per change detection check, which reduces selection work.
  • The internal virtual scroll containers no longer add a nested list role, which keeps the existing listbox and option semantics intact.

IgxDropDownComponent now accepts a content-projected igx-virtual-scroll as well as *igxFor, which keeps working as documented. Selection and navigation behave the same with either.

Angular Signal Forms support in Ignite UI for Angular form controls

Ignite UI for Angular 22.2 binds ten form controls to Angular Signal Forms through [formField]: igxInput, igx-checkbox, igx-switch, igx-radio-group, igx-select, igx-combo, igx-simple-combo, igx-date-picker, igx-time-picker and igx-date-range-picker. Validity, touched, dirty, disabled and required state are read from the signal-backed field, and no ReactiveFormsModule import is needed.

Signal Forms ship as public API in Angular 22 under @angular/forms/signals. Reactive and template-driven forms keep working with the same controls: 22.2 adds a path, it does not replace one.

import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { FormField, disabled, form, required, submit } from '@angular/forms/signals';
import { IGX_INPUT_GROUP_DIRECTIVES } from 'igniteui-angular/input-group';
import { IgxSelectComponent, IgxSelectItemComponent } from 'igniteui-angular/select';
import { IgxCheckboxComponent } from 'igniteui-angular/checkbox';

@Component({
  selector: 'app-signup',
  imports: [FormField, IGX_INPUT_GROUP_DIRECTIVES, IgxSelectComponent, IgxSelectItemComponent, IgxCheckboxComponent],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <form (submit)="onSubmit($event)">
      <igx-input-group>
        <label igxLabel>Name</label>
        <input igxInput [formField]="signup.name" />
        @for (error of signup.name().errors(); track error.kind) {
          <igx-hint>{{ error.message }}</igx-hint>
        }
      </igx-input-group>

      <igx-select [formField]="signup.role">
        <label igxLabel>Role</label>
        @for (r of roles; track r) {
          <igx-select-item [value]="r">{{ r }}</igx-select-item>
        }
      </igx-select>

      <igx-checkbox [formField]="signup.terms">Accept terms</igx-checkbox>
      <button type="submit">Sign up</button>
    </form>
  `
})
export class SignupComponent {
  model = signal({ name: '', role: '', terms: false });
  roles = ['Admin', 'User'];

  signup = form(this.model, (path) => {
    required(path.name, { message: 'Name is required' });
    required(path.role);
    required(path.terms);
    disabled(path.role, { when: ({ valueOf }) => valueOf(path.name) === '' });
  });

  onSubmit(event: Event) {
    event.preventDefault();
    submit(this.signup, async () => undefined);
  }
}

The example comes from the Ignite UI for Angular components agent skill shipped in the 22.2.0 package. igx-select opens an overlay, so the application also needs provideAnimations() in app.config.ts. submit() marks every field as touched, so invalid controls show their error state the way markAllAsTouched() does in reactive forms.

Related Angular form changes in 22.2.0:

  • igx-checkbox, igx-switch and igx-radio-group report required and aria-required for Validators.requiredTrue, as igxInput already did.
  • igx-radio-group implements setDisabledState, so control.disable(), enable() and the Signal Forms disabled rule reach the radio buttons.
  • Inputs, selects, combos and pickers no longer paint the invalid style while an async validator is pending.
  • igx-radio-group fires change once per selection, marks the bound control as touched on blur, and re-evaluates the invalid state when the control’s status changes.
  • IgcFormControlDirective supports igc-color-picker, so the Web Components color picker binds with ngModel and formControlName inside an Angular application.

Why your Ignite UI for Angular scrollbar theme looks different after 22.2

Ignite UI for Angular 22.2 styles scrollbars with the standard scrollbar-color and scrollbar-width CSS properties instead of the ::-webkit-scrollbar-* pseudo-elements. As a result, scrollbar-theme() keeps two working arguments, $sb-thumb-bg-color and $sb-track-bg-color, and every other argument is accepted but ignored.

Picture a design system with a half-rem scrollbar, a rounded thumb and a darker hover color, applied across an Angular application that hosts the Angular Data Grid. After the upgrade the theme still compiles. The thumb is square, the hover color is gone, and the width is whatever the browser draws for auto. Nothing errors, and that silence is why I would put this change first on a visual-regression checklist.

The cause is the standard property set itself: it exposes two colors and three width keywords (auto, thin, none), so a length cannot drive scrollbar-width.

scrollbar-theme() argument Status in 22.2
$sb-thumb-bg-color, $sb-track-bg-color Work as before
$sb-size No effect; set --sb-width: thin, or scrollbar-width: thin on the scrolling element
$sb-thumb-bg-color-hover, $sb-track-bg-color-hover No effect
$sb-thumb-min-height, $sb-thumb-border-color, $sb-thumb-border-size, $sb-thumb-border-radius No effect
$sb-track-border-color, $sb-track-border-size No effect
$sb-corner-bg, $sb-corner-border-color, $sb-corner-border-size No effect

The ng update migration for 22.2.0 removes the ignored arguments, including $sb-size, from existing scrollbar-theme(...) calls. A theme that set the design above changes like this:

@use 'igniteui-angular/theming' as *;

// Before ng update: these arguments still compile in 22.2, but most are now ignored
$my-scrollbar: scrollbar-theme(
  $sb-size: 0.5rem,
  $sb-thumb-bg-color: var(--ig-primary-300),
  $sb-thumb-bg-color-hover: var(--ig-primary-500),
  $sb-thumb-border-radius: 0.25rem,
  $sb-track-bg-color: var(--ig-gray-100),
);

:root {
  @include tokens($my-scrollbar);
}
@use 'igniteui-angular/theming' as *;

// After ng update: only the two colors the standard properties can express remain
$my-scrollbar: scrollbar-theme(
  $sb-thumb-bg-color: var(--ig-primary-300),
  $sb-track-bg-color: var(--ig-gray-100),
);

:root {
  @include tokens($my-scrollbar);
  // scrollbar-width takes auto, thin or none, so a length can no longer set the thickness
  --sb-width: thin;
}

Three more details decide whether the result matches the design:

  • If you override the scrollbar tokens on a nested scope, re-declare scrollbar-color and scrollbar-width on that scope as well. Both properties resolve their var() references on the element that declares them, and descendants inherit the resolved value. The library does this itself for igx-grid and the rest of the grid family, igx-query-builder, igx-column-actions and the Excel-style filtering menus, whose scrollbars follow their own background and foreground colors.
  • Scrollbar arrow buttons cannot be styled through the standard properties, and scrollbar-width: thin removes them where the platform draws them.
  • Firefox versions before 64 do not support scrollbar-color or scrollbar-width and render default scrollbars.

Is there a way back to a rounded thumb or a hover color? Not through scrollbar-theme() in 22.2. If a design system requires either, that requirement needs a conversation with its owner before the upgrade, not after it.

Grid summary borders now follow the Angular Data Grid border widths

In Ignite UI for Angular 22.2, grid-summary-theme() no longer accepts $border-width and $pinned-border-width, and the --ig-grid-summary-border-width and --ig-grid-summary-pinned-border-width CSS custom properties are removed. A summary cell takes its border width from grid-theme(): $header-border-width for the cell separator and $pinned-border-width for the pinned border.

The reasoning is visual continuity. A summary border continues a column border, so it can no longer be thicker or thinner than the border it continues. Border styles and colors stay themable through $border-style, $pinned-border-style, $border-color and $pinned-border-color, and through their CSS custom properties.

The ng update migration drops the removed arguments from grid-summary-theme(...) calls and renames the removed custom properties to the grid properties that now drive them. Review every replacement where a summary-only width was set: those grid properties also style the Data Grid’s own borders, so a migrated override now changes more than the summary row.

Button group and button directive API changes in Ignite UI for Angular 22.2

Ignite UI for Angular 22.2 types the IgxButtonGroupComponent values input as IButtonGroupButton[], removes the multiSelection input that was deprecated in 16.1.0, and removes five members from IgxButtonDirective and IgxIconButtonDirective.

The IButtonGroupButton interface describes each button configured through values: label, icon, ripple, selected, disabled and togglable. Every item requires a label, so collections without one stop compiling, and values now defaults to an empty array instead of undefined. Buttons rendered from values are tracked by label rather than by object identity: replacing an item with a new object that has the same label updates the existing button, so keep labels unique.

multiSelection becomes selectionMode="multi". The ng update migration rewrites it in templateUrl files and inline template strings. Inline templates that contain ${} interpolations, and references in TypeScript code, need a manual edit. The Angular template below imports IGX_BUTTON_GROUP_DIRECTIVES from igniteui-angular/button-group:

<!-- Before: multiSelection is removed in 22.2 -->
<igx-buttongroup [multiSelection]="true">
  <button igxButton [selected]="true">Bold</button>
  <button igxButton>Italic</button>
  <button igxButton>Underline</button>
</igx-buttongroup>

<!-- After -->
<igx-buttongroup selectionMode="multi">
  <button igxButton [selected]="true">Bold</button>
  <button igxButton>Italic</button>
  <button igxButton>Underline</button>
</igx-buttongroup>

On IgxButtonDirective and IgxIconButtonDirective, the element, role, focused, select() and deselect() members are gone. Use nativeElement instead of element, set role in the template, and bind selected instead of calling select() or deselect(). IgxButtonGroupComponent keeps its selectButton() and deselectButton() methods.

Pivot Grid and Tree Grid templates in standalone Angular components (22.2.1)

Ignite UI for Angular 22.2.1 adds two template directives to the standalone directive arrays, so both templates can be declared inside the grid in standalone components:

  • IgxPivotRowDimensionHeaderTemplateDirective (igxPivotRowDimensionHeader) is now part of IGX_PIVOT_GRID_DIRECTIVES and IgxPivotGridModule, for the Pivot Grid row dimension header template.
  • IgxRowLoadingIndicatorTemplateDirective (igxRowLoadingIndicator) is now exported from igniteui-angular/grids/tree-grid and included in IGX_TREE_GRID_DIRECTIVES, for the Tree Grid row loading indicator shown with loadChildrenOnDemand.

Deprecations and behavioral changes in the Ignite UI for Angular grids (22.2.1)

Ignite UI for Angular 22.2.1 deprecates four GridBaseAPIService members and one IgxFilteringService method, all scheduled for removal in a future version. Each has a public replacement on the grid or the column:

Deprecated API Replacement
GridBaseAPIService.get_rec_id_by_index The record at the index in the grid data, and its primaryKey value
GridBaseAPIService.sort_decoupled The grid groupBy method
GridBaseAPIService.get_filtered_data The grid filteredData property
GridBaseAPIService.getSortStrategyPerColumn (protected) The column sortStrategy property
IgxFilteringService.filter_global The grid filteringExpressionsTree property

prepare_sorting_expression and prepare_grouping_expression, and prepare_sorting_expression in GridServiceType, now take a single expressions collection instead of an array of collections.

Two behavioral changes can alter existing code paths:

  • In the Tree Grid, beginAddRowByIndex(index, true) now opens the add row UI for a child of the row at index, as documented; previously the parent was the row at index - 1. beginAddRowByIndex(0) now adds the first record, as in the other grids, instead of logging a warning.
  • In the Data Grid, Tree Grid, Hierarchical Grid and Pivot Grid, calling filter without a condition for a column that has no filtering expressions now throws Invalid condition or Expression Tree!, even when a filtering event handler sets expressions for that column.

PDF export changes in Ignite UI for Angular 22.2

In Ignite UI for Angular 22.2, IgxPdfExporterService shades summary rows like the header row of the exported table, and the shading follows the showTableBorders option. The reasoning in the changelog: a summary closes the rows above it the way the header opens them, so it should not read as one more record.

Pivot Grid exports change in two more ways. Row dimension cells are shaded the same way, because they head the record they sit on. A row dimension value that repeats down consecutive records is drawn once, in a single merged cell, the way the Pivot Grid merges its own row headers. Values merge only under the same parent dimension, and a merged cell that would cross the bottom of a page is cut there and reopened under the headers of the next page.

Exported reports look different after the upgrade, so any process that parses or compares PDF output needs a fresh baseline.

Other fixes in Ignite UI for Angular 22.2

Ignite UI for Angular 22.2.0 and 22.2.1 also ship these fixes, grouped by component:

Component Fix Version
Data Grid, Tree Grid, Hierarchical Grid, Pivot Grid Copying with only columns selected copies the selected columns’ data 22.2.1
Data Grid, Tree Grid, Hierarchical Grid, Pivot Grid pin(index) no longer throws when the target pinning area is empty, and unpin(index) no longer throws when all columns are pinned 22.2.1
Data Grid, Tree Grid, Hierarchical Grid, Pivot Grid navigateTo with a callback no longer throws with remote virtualization when the target row is not loaded 22.2.1
Tree Grid Excel-style filtering lists column values with a custom strategy that extends FilteringStrategy 22.2.1
Hierarchical Grid expandChildren applies to child grids rendered later, and nested row islands added with @if register under their parent 22.2.1
Grid Lite A sort or filter from the UI runs the data pipeline once, so dataPipelineConfiguration hooks no longer fire twice 22.2.0
Checkbox, Ripple The tick mark renders correctly inside CSS-scoped subtrees that use a different design system than the application 22.2.0
Navigation Drawer Fast touch movements below the pan threshold no longer toggle the drawer 22.2.0
Month Picker aria-activedescendant follows the active month or year during keyboard navigation 22.2.0
Migrations Theme-argument migrations preserve comments and process stylesheets outside sourceRoot 22.2.0

The full set of changes, including fixes not listed here, is in the Ignite UI for Angular CHANGELOG on GitHub.

How to upgrade to Ignite UI for Angular 22.2

Upgrading to Ignite UI for Angular 22.2 starts with Angular 22, because the 22.2 packages declare Angular 22 as their peer dependency. Then:

  1. Run ng update to list the available migrations, then ng update igniteui-angular, using @infragistics/igniteui-angular instead if the project depends on the licensed package.
  2. Search TypeScript files, and inline templates with ${} interpolations, for multiSelection and replace it with selectionMode.
  3. Replace element, role, focused, select() and deselect() on IgxButtonDirective and IgxIconButtonDirective.
  4. Give every item in a button group values collection a unique label.
  5. Update end-to-end selectors and CSS that target igx-display-container or igx-vhelper--vertical inside combos and Excel-style filtering.
  6. Review the custom properties the migration renamed in grid-summary-theme overrides.
  7. Compare scrollbars and summary borders visually, and set --sb-width: thin where a thinner scrollbar is required.
  8. Replace calls to the GridBaseAPIService and IgxFilteringService members deprecated in 22.2.1.

Frequently asked questions about Ignite UI for Angular 22.2

Does Ignite UI for Angular 22.2 have breaking changes?

Yes. Ignite UI for Angular 22.2.0 turns most scrollbar-theme arguments into no-ops, removes the grid-summary-theme border width arguments, removes the button group multiSelection input, types the button group values input, and removes five members from IgxButtonDirective and IgxIconButtonDirective. The ng update migration handles the theming arguments and multiSelection in templates, and the rest needs manual edits.

Which Angular version does Ignite UI for Angular 22.2 require?

Ignite UI for Angular 22.2 requires Angular 22. The igniteui-angular 22.2 packages declare version 22 of @angular/core, @angular/common, @angular/forms and @angular/animations as peer dependencies.

Does IgxVirtualScrollComponent replace the igxFor directive?

No. The igxFor directive keeps working as documented, and IgxDropDownComponent accepts either igxFor or a content-projected igx-virtual-scroll. In Ignite UI for Angular 22.2, the Combo, the Simple Combo and the Excel-style filtering search list switched internally to IgxVirtualScrollComponent.

Does ng update migrate Ignite UI for Angular 22.2 automatically?

Partly. The 22.2.0 migrations remove the ignored scrollbar-theme arguments, drop the removed grid-summary-theme border widths and rename their custom properties, and replace multiSelection with selectionMode in component templates. TypeScript references to multiSelection, inline templates with interpolations, the removed button directive members, and test selectors for the old combo markup need manual changes.

What did Ignite UI for Angular 22.2.1 deprecate?

Ignite UI for Angular 22.2.1 deprecates get_rec_id_by_index, sort_decoupled, get_filtered_data and the protected getSortStrategyPerColumn on GridBaseAPIService, and filter_global on IgxFilteringService. Their replacements are the grid data with its primaryKey value, the grid groupBy method, the grid filteredData property, the column sortStrategy property and the grid filteringExpressionsTree property.