diff --git a/angular-workspace/projects/example-client-app/src/app/app.module.ts b/angular-workspace/projects/example-client-app/src/app/app.module.ts
index f63269e4f5..45721b321b 100644
--- a/angular-workspace/projects/example-client-app/src/app/app.module.ts
+++ b/angular-workspace/projects/example-client-app/src/app/app.module.ts
@@ -13,11 +13,14 @@ import { NimbleTextAreaModule, NimbleTextFieldModule, NimbleNumberFieldModule, N
import { NimbleLabelProviderCoreModule } from '@ni/nimble-angular/label-provider/core';
import { NimbleLabelProviderTableModule } from '@ni/nimble-angular/label-provider/table';
import { NimbleMappingTextModule } from '@ni/nimble-angular/mapping/text';
+import { NimbleMappingIconModule } from '@ni/nimble-angular/mapping/icon';
+import { NimbleMappingSpinnerModule } from '@ni/nimble-angular/mapping/spinner';
import { NimbleTableModule } from '@ni/nimble-angular/table';
import { NimbleTableColumnTextModule } from '@ni/nimble-angular/table-column/text';
import { NimbleTableColumnAnchorModule } from '@ni/nimble-angular/table-column/anchor';
import { NimbleTableColumnDateTextModule } from '@ni/nimble-angular/table-column/date-text';
import { NimbleTableColumnEnumTextModule } from '@ni/nimble-angular/table-column/enum-text';
+import { NimbleTableColumnIconModule } from '@ni/nimble-angular/table-column/icon';
import { NimbleRichTextViewerModule } from '@ni/nimble-angular/rich-text-viewer';
import { AppComponent } from './app.component';
import { CustomAppComponent } from './customapp/customapp.component';
@@ -81,6 +84,9 @@ import { HeaderComponent } from './header/header.component';
NimbleMappingTextModule,
NimbleBannerModule,
NimbleRichTextViewerModule,
+ NimbleTableColumnIconModule,
+ NimbleMappingIconModule,
+ NimbleMappingSpinnerModule,
RouterModule.forRoot(
[
{ path: '', redirectTo: '/customapp', pathMatch: 'full' },
diff --git a/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.html b/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.html
index d7c0a5654a..8f42865860 100644
--- a/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.html
+++ b/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.html
@@ -222,6 +222,22 @@
Status
+
+
+
+
+
+ Result
+
String 2
diff --git a/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.ts b/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.ts
index 9687744301..d39d1b18fc 100644
--- a/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.ts
+++ b/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.ts
@@ -18,6 +18,7 @@ interface SimpleTableRecord extends TableRecord {
linkLabel?: string;
date: number;
statusCode: number;
+ result: string;
}
@Component({
@@ -109,7 +110,8 @@ export class CustomAppComponent {
href: '/customapp',
linkLabel: 'Link',
date: (tableData.length % 2 === 0) ? new Date(2023, 7, 16, 3, 56, 11).valueOf() : new Date(2022, 2, 7, 20, 28, 41).valueOf(),
- statusCode: (tableData.length % 2 === 0) ? 100 : 101
+ statusCode: (tableData.length % 2 === 0) ? 100 : 101,
+ result: (tableData.length % 2 === 0) ? 'success' : 'unknown'
});
this.tableDataSubject.next(tableData);
}
diff --git a/angular-workspace/projects/ni/nimble-angular/mapping/icon/ng-package.json b/angular-workspace/projects/ni/nimble-angular/mapping/icon/ng-package.json
new file mode 100644
index 0000000000..e5440110fb
--- /dev/null
+++ b/angular-workspace/projects/ni/nimble-angular/mapping/icon/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "$schema": "../../../../../../node_modules/ng-packagr/ng-package.schema.json",
+ "lib": {
+ "entryFile": "public-api.ts"
+ }
+}
\ No newline at end of file
diff --git a/angular-workspace/projects/ni/nimble-angular/mapping/icon/nimble-mapping-icon.directive.ts b/angular-workspace/projects/ni/nimble-angular/mapping/icon/nimble-mapping-icon.directive.ts
new file mode 100644
index 0000000000..d37ea1c02e
--- /dev/null
+++ b/angular-workspace/projects/ni/nimble-angular/mapping/icon/nimble-mapping-icon.directive.ts
@@ -0,0 +1,49 @@
+import { Directive, ElementRef, Input, Renderer2 } from '@angular/core';
+import { type MappingIcon, mappingIconTag } from '@ni/nimble-components/dist/esm/mapping/icon';
+import type { MappingKey } from '@ni/nimble-components/dist/esm/mapping/base/types';
+import type { IconSeverity } from '@ni/nimble-components/dist/esm/icon-base/types';
+
+export type { MappingIcon };
+export { mappingIconTag };
+
+/**
+ * Directive to provide Angular integration for the mapping icon element used by the icon column.
+ */
+@Directive({
+ selector: 'nimble-mapping-icon'
+})
+export class NimbleMappingIconDirective {
+ public get key(): MappingKey | undefined {
+ return this.elementRef.nativeElement.key;
+ }
+
+ @Input() public set key(value: MappingKey | undefined) {
+ this.renderer.setProperty(this.elementRef.nativeElement, 'key', value);
+ }
+
+ public get text(): string | undefined {
+ return this.elementRef.nativeElement.text;
+ }
+
+ @Input() public set text(value: string | undefined) {
+ this.renderer.setProperty(this.elementRef.nativeElement, 'text', value);
+ }
+
+ public get icon(): string | undefined {
+ return this.elementRef.nativeElement.icon;
+ }
+
+ @Input() public set icon(value: string | undefined) {
+ this.renderer.setProperty(this.elementRef.nativeElement, 'icon', value);
+ }
+
+ public get severity(): IconSeverity {
+ return this.elementRef.nativeElement.severity;
+ }
+
+ @Input() public set severity(value: IconSeverity) {
+ this.renderer.setProperty(this.elementRef.nativeElement, 'severity', value);
+ }
+
+ public constructor(protected readonly renderer: Renderer2, protected readonly elementRef: ElementRef) {}
+}
\ No newline at end of file
diff --git a/angular-workspace/projects/ni/nimble-angular/mapping/icon/nimble-mapping-icon.module.ts b/angular-workspace/projects/ni/nimble-angular/mapping/icon/nimble-mapping-icon.module.ts
new file mode 100644
index 0000000000..ede6667b5b
--- /dev/null
+++ b/angular-workspace/projects/ni/nimble-angular/mapping/icon/nimble-mapping-icon.module.ts
@@ -0,0 +1,12 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { NimbleMappingIconDirective } from './nimble-mapping-icon.directive';
+
+import '@ni/nimble-components/dist/esm/mapping/icon';
+
+@NgModule({
+ declarations: [NimbleMappingIconDirective],
+ imports: [CommonModule],
+ exports: [NimbleMappingIconDirective]
+})
+export class NimbleMappingIconModule { }
\ No newline at end of file
diff --git a/angular-workspace/projects/ni/nimble-angular/mapping/icon/public-api.ts b/angular-workspace/projects/ni/nimble-angular/mapping/icon/public-api.ts
new file mode 100644
index 0000000000..d0b64e72ff
--- /dev/null
+++ b/angular-workspace/projects/ni/nimble-angular/mapping/icon/public-api.ts
@@ -0,0 +1,2 @@
+export * from './nimble-mapping-icon.directive';
+export * from './nimble-mapping-icon.module';
\ No newline at end of file
diff --git a/angular-workspace/projects/ni/nimble-angular/mapping/icon/tests/nimble-mapping-icon.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/mapping/icon/tests/nimble-mapping-icon.directive.spec.ts
new file mode 100644
index 0000000000..8ad4f354e3
--- /dev/null
+++ b/angular-workspace/projects/ni/nimble-angular/mapping/icon/tests/nimble-mapping-icon.directive.spec.ts
@@ -0,0 +1,251 @@
+import { Component, ElementRef, ViewChild } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { IconSeverity } from '@ni/nimble-angular';
+import { NimbleTableModule } from '../../../table/nimble-table.module';
+import { NimbleTableColumnIconModule } from '../../../table-column/icon/nimble-table-column-icon.module';
+import { NimbleMappingIconDirective, type MappingIcon } from '../nimble-mapping-icon.directive';
+import { NimbleMappingIconModule } from '../nimble-mapping-icon.module';
+
+describe('NimbleMappingIcon', () => {
+ describe('module', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [NimbleMappingIconModule]
+ });
+ });
+
+ it('custom element is defined', () => {
+ expect(customElements.get('nimble-mapping-text')).not.toBeUndefined();
+ });
+ });
+
+ describe('with template string values', () => {
+ @Component({
+ template: `
+
+
+
+
+
+
+ `
+ })
+ class TestHostComponent {
+ @ViewChild('mapping', { read: NimbleMappingIconDirective }) public directive: NimbleMappingIconDirective;
+ @ViewChild('mapping', { read: ElementRef }) public elementRef: ElementRef;
+ }
+
+ let fixture: ComponentFixture;
+ let directive: NimbleMappingIconDirective;
+ let nativeElement: MappingIcon;
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [TestHostComponent],
+ imports: [NimbleMappingIconModule, NimbleTableColumnIconModule, NimbleTableModule]
+ });
+
+ fixture = TestBed.createComponent(TestHostComponent);
+ fixture.detectChanges();
+ directive = fixture.componentInstance.directive;
+ nativeElement = fixture.componentInstance.elementRef.nativeElement;
+ });
+
+ it('will use template string values for key', () => {
+ expect(directive.key).toBe('false');
+ expect(nativeElement.key).toBe('false');
+ });
+
+ it('will use template string values for text', () => {
+ expect(directive.text).toBe('nope');
+ expect(nativeElement.text).toBe('nope');
+ });
+
+ it('will use template string values for icon', () => {
+ expect(directive.icon).toBe('nimble-icon-xmark');
+ expect(nativeElement.icon).toBe('nimble-icon-xmark');
+ });
+
+ it('will use template string values for severity', () => {
+ expect(directive.severity).toBe('error');
+ expect(nativeElement.severity).toBe('error');
+ });
+ });
+
+ describe('with property bound values', () => {
+ @Component({
+ template: `
+
+
+
+
+
+
+ `
+ })
+ class TestHostComponent {
+ @ViewChild('mapping', { read: NimbleMappingIconDirective }) public directive: NimbleMappingIconDirective;
+ @ViewChild('mapping', { read: ElementRef }) public elementRef: ElementRef;
+ public key = false;
+ public text = 'nope';
+ public icon = 'nimble-icon-xmark';
+ public severity: IconSeverity = IconSeverity.error;
+ }
+
+ let fixture: ComponentFixture;
+ let directive: NimbleMappingIconDirective;
+ let nativeElement: MappingIcon;
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [TestHostComponent],
+ imports: [NimbleMappingIconModule, NimbleTableColumnIconModule, NimbleTableModule]
+ });
+
+ fixture = TestBed.createComponent(TestHostComponent);
+ fixture.detectChanges();
+ directive = fixture.componentInstance.directive;
+ nativeElement = fixture.componentInstance.elementRef.nativeElement;
+ });
+
+ it('can be configured with property binding for key', () => {
+ expect(directive.key).toBeFalse();
+ expect(nativeElement.key).toBeFalse();
+
+ fixture.componentInstance.key = true;
+ fixture.detectChanges();
+
+ expect(directive.key).toBeTrue();
+ expect(nativeElement.key).toBeTrue();
+ });
+
+ it('can be configured with property binding for text', () => {
+ expect(directive.text).toBe('nope');
+ expect(nativeElement.text).toBe('nope');
+
+ fixture.componentInstance.text = 'yep';
+ fixture.detectChanges();
+
+ expect(directive.text).toBe('yep');
+ expect(nativeElement.text).toBe('yep');
+ });
+
+ it('can be configured with property binding for icon', () => {
+ expect(directive.icon).toBe('nimble-icon-xmark');
+ expect(nativeElement.icon).toBe('nimble-icon-xmark');
+
+ fixture.componentInstance.icon = 'nimble-icon-check';
+ fixture.detectChanges();
+
+ expect(directive.icon).toBe('nimble-icon-check');
+ expect(nativeElement.icon).toBe('nimble-icon-check');
+ });
+
+ it('can be configured with property binding for severity', () => {
+ expect(directive.severity).toBe('error');
+ expect(nativeElement.severity).toBe('error');
+
+ fixture.componentInstance.severity = IconSeverity.success;
+ fixture.detectChanges();
+
+ expect(directive.severity).toBe('success');
+ expect(nativeElement.severity).toBe('success');
+ });
+ });
+
+ describe('with attribute bound values', () => {
+ @Component({
+ template: `
+
+
+
+
+
+
+ `
+ })
+ class TestHostComponent {
+ @ViewChild('mapping', { read: NimbleMappingIconDirective }) public directive: NimbleMappingIconDirective;
+ @ViewChild('mapping', { read: ElementRef }) public elementRef: ElementRef;
+ public key = false;
+ public text = 'nope';
+ public icon = 'nimble-icon-xmark';
+ public severity: IconSeverity = IconSeverity.error;
+ }
+
+ let fixture: ComponentFixture;
+ let directive: NimbleMappingIconDirective;
+ let nativeElement: MappingIcon;
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [TestHostComponent],
+ imports: [NimbleMappingIconModule, NimbleTableColumnIconModule, NimbleTableModule]
+ });
+
+ fixture = TestBed.createComponent(TestHostComponent);
+ fixture.detectChanges();
+ directive = fixture.componentInstance.directive;
+ nativeElement = fixture.componentInstance.elementRef.nativeElement;
+ });
+
+ it('can be configured with attribute binding for key', () => {
+ expect(directive.key).toBe('false');
+ expect(nativeElement.key).toBe('false');
+
+ fixture.componentInstance.key = true;
+ fixture.detectChanges();
+
+ expect(directive.key).toBe('true');
+ expect(nativeElement.key).toBe('true');
+ });
+
+ it('can be configured with attribute binding for text', () => {
+ expect(directive.text).toBe('nope');
+ expect(nativeElement.text).toBe('nope');
+
+ fixture.componentInstance.text = 'yep';
+ fixture.detectChanges();
+
+ expect(directive.text).toBe('yep');
+ expect(nativeElement.text).toBe('yep');
+ });
+
+ it('can be configured with property binding for icon', () => {
+ expect(directive.icon).toBe('nimble-icon-xmark');
+ expect(nativeElement.icon).toBe('nimble-icon-xmark');
+
+ fixture.componentInstance.icon = 'nimble-icon-check';
+ fixture.detectChanges();
+
+ expect(directive.icon).toBe('nimble-icon-check');
+ expect(nativeElement.icon).toBe('nimble-icon-check');
+ });
+
+ it('can be configured with property binding for severity', () => {
+ expect(directive.severity).toBe('error');
+ expect(nativeElement.severity).toBe('error');
+
+ fixture.componentInstance.severity = IconSeverity.success;
+ fixture.detectChanges();
+
+ expect(directive.severity).toBe('success');
+ expect(nativeElement.severity).toBe('success');
+ });
+ });
+});
\ No newline at end of file
diff --git a/angular-workspace/projects/ni/nimble-angular/mapping/spinner/ng-package.json b/angular-workspace/projects/ni/nimble-angular/mapping/spinner/ng-package.json
new file mode 100644
index 0000000000..e5440110fb
--- /dev/null
+++ b/angular-workspace/projects/ni/nimble-angular/mapping/spinner/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "$schema": "../../../../../../node_modules/ng-packagr/ng-package.schema.json",
+ "lib": {
+ "entryFile": "public-api.ts"
+ }
+}
\ No newline at end of file
diff --git a/angular-workspace/projects/ni/nimble-angular/mapping/spinner/nimble-mapping-spinner.directive.ts b/angular-workspace/projects/ni/nimble-angular/mapping/spinner/nimble-mapping-spinner.directive.ts
new file mode 100644
index 0000000000..96de8801d2
--- /dev/null
+++ b/angular-workspace/projects/ni/nimble-angular/mapping/spinner/nimble-mapping-spinner.directive.ts
@@ -0,0 +1,32 @@
+import { Directive, ElementRef, Input, Renderer2 } from '@angular/core';
+import { type MappingSpinner, mappingSpinnerTag } from '@ni/nimble-components/dist/esm/mapping/spinner';
+import type { MappingKey } from '@ni/nimble-components/dist/esm/mapping/base/types';
+
+export type { MappingSpinner };
+export { mappingSpinnerTag };
+
+/**
+ * Directive to provide Angular integration for the mapping spinner element used by the spinner column.
+ */
+@Directive({
+ selector: 'nimble-mapping-spinner'
+})
+export class NimbleMappingSpinnerDirective {
+ public get key(): MappingKey | undefined {
+ return this.elementRef.nativeElement.key;
+ }
+
+ @Input() public set key(value: MappingKey | undefined) {
+ this.renderer.setProperty(this.elementRef.nativeElement, 'key', value);
+ }
+
+ public get text(): string | undefined {
+ return this.elementRef.nativeElement.text;
+ }
+
+ @Input() public set text(value: string | undefined) {
+ this.renderer.setProperty(this.elementRef.nativeElement, 'text', value);
+ }
+
+ public constructor(protected readonly renderer: Renderer2, protected readonly elementRef: ElementRef) {}
+}
\ No newline at end of file
diff --git a/angular-workspace/projects/ni/nimble-angular/mapping/spinner/nimble-mapping-spinner.module.ts b/angular-workspace/projects/ni/nimble-angular/mapping/spinner/nimble-mapping-spinner.module.ts
new file mode 100644
index 0000000000..fac1a07768
--- /dev/null
+++ b/angular-workspace/projects/ni/nimble-angular/mapping/spinner/nimble-mapping-spinner.module.ts
@@ -0,0 +1,12 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { NimbleMappingSpinnerDirective } from './nimble-mapping-spinner.directive';
+
+import '@ni/nimble-components/dist/esm/mapping/spinner';
+
+@NgModule({
+ declarations: [NimbleMappingSpinnerDirective],
+ imports: [CommonModule],
+ exports: [NimbleMappingSpinnerDirective]
+})
+export class NimbleMappingSpinnerModule { }
\ No newline at end of file
diff --git a/angular-workspace/projects/ni/nimble-angular/mapping/spinner/public-api.ts b/angular-workspace/projects/ni/nimble-angular/mapping/spinner/public-api.ts
new file mode 100644
index 0000000000..3ffc908c64
--- /dev/null
+++ b/angular-workspace/projects/ni/nimble-angular/mapping/spinner/public-api.ts
@@ -0,0 +1,2 @@
+export * from './nimble-mapping-spinner.directive';
+export * from './nimble-mapping-spinner.module';
\ No newline at end of file
diff --git a/angular-workspace/projects/ni/nimble-angular/mapping/spinner/tests/nimble-mapping-spinner.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/mapping/spinner/tests/nimble-mapping-spinner.directive.spec.ts
new file mode 100644
index 0000000000..d90ef54c60
--- /dev/null
+++ b/angular-workspace/projects/ni/nimble-angular/mapping/spinner/tests/nimble-mapping-spinner.directive.spec.ts
@@ -0,0 +1,186 @@
+import { Component, ElementRef, ViewChild } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { NimbleTableModule } from '../../../table/nimble-table.module';
+import { NimbleTableColumnIconModule } from '../../../table-column/icon/nimble-table-column-icon.module';
+import { NimbleMappingSpinnerDirective, type MappingSpinner } from '../nimble-mapping-spinner.directive';
+import { NimbleMappingSpinnerModule } from '../nimble-mapping-spinner.module';
+
+describe('NimbleMappingSpinner', () => {
+ describe('module', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [NimbleMappingSpinnerModule]
+ });
+ });
+
+ it('custom element is defined', () => {
+ expect(customElements.get('nimble-mapping-spinner')).not.toBeUndefined();
+ });
+ });
+
+ describe('with template string values', () => {
+ @Component({
+ template: `
+
+
+
+
+
+
+ `
+ })
+ class TestHostComponent {
+ @ViewChild('mapping', { read: NimbleMappingSpinnerDirective }) public directive: NimbleMappingSpinnerDirective;
+ @ViewChild('mapping', { read: ElementRef }) public elementRef: ElementRef;
+ }
+
+ let fixture: ComponentFixture;
+ let directive: NimbleMappingSpinnerDirective;
+ let nativeElement: MappingSpinner;
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [TestHostComponent],
+ imports: [NimbleMappingSpinnerModule, NimbleTableColumnIconModule, NimbleTableModule]
+ });
+
+ fixture = TestBed.createComponent(TestHostComponent);
+ fixture.detectChanges();
+ directive = fixture.componentInstance.directive;
+ nativeElement = fixture.componentInstance.elementRef.nativeElement;
+ });
+
+ it('will use template string values for key', () => {
+ expect(directive.key).toBe('false');
+ expect(nativeElement.key).toBe('false');
+ });
+
+ it('will use template string values for text', () => {
+ expect(directive.text).toBe('nope');
+ expect(nativeElement.text).toBe('nope');
+ });
+ });
+
+ describe('with property bound values', () => {
+ @Component({
+ template: `
+
+
+
+
+
+
+ `
+ })
+ class TestHostComponent {
+ @ViewChild('mapping', { read: NimbleMappingSpinnerDirective }) public directive: NimbleMappingSpinnerDirective;
+ @ViewChild('mapping', { read: ElementRef }) public elementRef: ElementRef;
+ public key = false;
+ public text = 'nope';
+ }
+
+ let fixture: ComponentFixture;
+ let directive: NimbleMappingSpinnerDirective;
+ let nativeElement: MappingSpinner;
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [TestHostComponent],
+ imports: [NimbleMappingSpinnerModule, NimbleTableColumnIconModule, NimbleTableModule]
+ });
+
+ fixture = TestBed.createComponent(TestHostComponent);
+ fixture.detectChanges();
+ directive = fixture.componentInstance.directive;
+ nativeElement = fixture.componentInstance.elementRef.nativeElement;
+ });
+
+ it('can be configured with property binding for key', () => {
+ expect(directive.key).toBeFalse();
+ expect(nativeElement.key).toBeFalse();
+
+ fixture.componentInstance.key = true;
+ fixture.detectChanges();
+
+ expect(directive.key).toBeTrue();
+ expect(nativeElement.key).toBeTrue();
+ });
+
+ it('can be configured with property binding for text', () => {
+ expect(directive.text).toBe('nope');
+ expect(nativeElement.text).toBe('nope');
+
+ fixture.componentInstance.text = 'yep';
+ fixture.detectChanges();
+
+ expect(directive.text).toBe('yep');
+ expect(nativeElement.text).toBe('yep');
+ });
+ });
+
+ describe('with attribute bound values', () => {
+ @Component({
+ template: `
+
+
+
+
+
+
+ `
+ })
+ class TestHostComponent {
+ @ViewChild('mapping', { read: NimbleMappingSpinnerDirective }) public directive: NimbleMappingSpinnerDirective;
+ @ViewChild('mapping', { read: ElementRef }) public elementRef: ElementRef;
+ public key = false;
+ public text = 'nope';
+ }
+
+ let fixture: ComponentFixture;
+ let directive: NimbleMappingSpinnerDirective;
+ let nativeElement: MappingSpinner;
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [TestHostComponent],
+ imports: [NimbleMappingSpinnerModule, NimbleTableColumnIconModule, NimbleTableModule]
+ });
+
+ fixture = TestBed.createComponent(TestHostComponent);
+ fixture.detectChanges();
+ directive = fixture.componentInstance.directive;
+ nativeElement = fixture.componentInstance.elementRef.nativeElement;
+ });
+
+ it('can be configured with attribute binding for key', () => {
+ expect(directive.key).toBe('false');
+ expect(nativeElement.key).toBe('false');
+
+ fixture.componentInstance.key = true;
+ fixture.detectChanges();
+
+ expect(directive.key).toBe('true');
+ expect(nativeElement.key).toBe('true');
+ });
+
+ it('can be configured with attribute binding for text', () => {
+ expect(directive.text).toBe('nope');
+ expect(nativeElement.text).toBe('nope');
+
+ fixture.componentInstance.text = 'yep';
+ fixture.detectChanges();
+
+ expect(directive.text).toBe('yep');
+ expect(nativeElement.text).toBe('yep');
+ });
+ });
+});
\ No newline at end of file
diff --git a/angular-workspace/projects/ni/nimble-angular/table-column/icon/ng-package.json b/angular-workspace/projects/ni/nimble-angular/table-column/icon/ng-package.json
new file mode 100644
index 0000000000..e5440110fb
--- /dev/null
+++ b/angular-workspace/projects/ni/nimble-angular/table-column/icon/ng-package.json
@@ -0,0 +1,6 @@
+{
+ "$schema": "../../../../../../node_modules/ng-packagr/ng-package.schema.json",
+ "lib": {
+ "entryFile": "public-api.ts"
+ }
+}
\ No newline at end of file
diff --git a/angular-workspace/projects/ni/nimble-angular/table-column/icon/nimble-table-column-icon.directive.ts b/angular-workspace/projects/ni/nimble-angular/table-column/icon/nimble-table-column-icon.directive.ts
new file mode 100644
index 0000000000..e3f969ab36
--- /dev/null
+++ b/angular-workspace/projects/ni/nimble-angular/table-column/icon/nimble-table-column-icon.directive.ts
@@ -0,0 +1,80 @@
+import { Directive, ElementRef, Input, Renderer2 } from '@angular/core';
+import { type TableColumnIcon, tableColumnIconTag } from '@ni/nimble-components/dist/esm/table-column/icon';
+import { BooleanValueOrAttribute, NumberValueOrAttribute, toBooleanProperty, toNullableNumberProperty } from '@ni/nimble-angular/internal-utilities';
+import { NimbleTableColumnBaseDirective } from '@ni/nimble-angular/table-column';
+import type { MappingKeyType } from '@ni/nimble-components/dist/esm/table-column/enum-base/types';
+
+export type { TableColumnIcon };
+export { tableColumnIconTag };
+
+/**
+ * Directive to provide Angular integration for the table column element for icons/spinners.
+ */
+@Directive({
+ selector: 'nimble-table-column-icon'
+})
+export class NimbleTableColumnIconDirective extends NimbleTableColumnBaseDirective {
+ public get fieldName(): string | undefined {
+ return this.elementRef.nativeElement.fieldName;
+ }
+
+ // Renaming because property should have camel casing, but attribute should not
+ // eslint-disable-next-line @angular-eslint/no-input-rename
+ @Input('field-name') public set fieldName(value: string | undefined) {
+ this.renderer.setProperty(this.elementRef.nativeElement, 'fieldName', value);
+ }
+
+ public get keyType(): MappingKeyType {
+ return this.elementRef.nativeElement.keyType;
+ }
+
+ // Renaming because property should have camel casing, but attribute should not
+ // eslint-disable-next-line @angular-eslint/no-input-rename
+ @Input('key-type') public set keyType(value: MappingKeyType) {
+ this.renderer.setProperty(this.elementRef.nativeElement, 'keyType', value);
+ }
+
+ public get fractionalWidth(): number | null | undefined {
+ return this.elementRef.nativeElement.fractionalWidth;
+ }
+
+ // Renaming because property should have camel casing, but attribute should not
+ // eslint-disable-next-line @angular-eslint/no-input-rename
+ @Input('fractional-width') public set fractionalWidth(value: NumberValueOrAttribute | null | undefined) {
+ this.renderer.setProperty(this.elementRef.nativeElement, 'fractionalWidth', toNullableNumberProperty(value));
+ }
+
+ public get minPixelWidth(): number | null | undefined {
+ return this.elementRef.nativeElement.minPixelWidth;
+ }
+
+ // Renaming because property should have camel casing, but attribute should not
+ // eslint-disable-next-line @angular-eslint/no-input-rename
+ @Input('min-pixel-width') public set minPixelWidth(value: NumberValueOrAttribute | null | undefined) {
+ this.renderer.setProperty(this.elementRef.nativeElement, 'minPixelWidth', toNullableNumberProperty(value));
+ }
+
+ public get groupIndex(): number | null | undefined {
+ return this.elementRef.nativeElement.groupIndex;
+ }
+
+ // Renaming because property should have camel casing, but attribute should not
+ // eslint-disable-next-line @angular-eslint/no-input-rename
+ @Input('group-index') public set groupIndex(value: NumberValueOrAttribute | null | undefined) {
+ this.renderer.setProperty(this.elementRef.nativeElement, 'groupIndex', toNullableNumberProperty(value));
+ }
+
+ public get groupingDisabled(): boolean {
+ return this.elementRef.nativeElement.groupingDisabled;
+ }
+
+ // Renaming because property should have camel casing, but attribute should not
+ // eslint-disable-next-line @angular-eslint/no-input-rename
+ @Input('grouping-disabled') public set groupingDisabled(value: BooleanValueOrAttribute) {
+ this.renderer.setProperty(this.elementRef.nativeElement, 'groupingDisabled', toBooleanProperty(value));
+ }
+
+ public constructor(renderer: Renderer2, elementRef: ElementRef) {
+ super(renderer, elementRef);
+ }
+}
diff --git a/angular-workspace/projects/ni/nimble-angular/table-column/icon/nimble-table-column-icon.module.ts b/angular-workspace/projects/ni/nimble-angular/table-column/icon/nimble-table-column-icon.module.ts
new file mode 100644
index 0000000000..d3d95db680
--- /dev/null
+++ b/angular-workspace/projects/ni/nimble-angular/table-column/icon/nimble-table-column-icon.module.ts
@@ -0,0 +1,12 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { NimbleTableColumnIconDirective } from './nimble-table-column-icon.directive';
+
+import '@ni/nimble-components/dist/esm/table-column/icon';
+
+@NgModule({
+ declarations: [NimbleTableColumnIconDirective],
+ imports: [CommonModule],
+ exports: [NimbleTableColumnIconDirective]
+})
+export class NimbleTableColumnIconModule { }
diff --git a/angular-workspace/projects/ni/nimble-angular/table-column/icon/public-api.ts b/angular-workspace/projects/ni/nimble-angular/table-column/icon/public-api.ts
new file mode 100644
index 0000000000..209eb764b2
--- /dev/null
+++ b/angular-workspace/projects/ni/nimble-angular/table-column/icon/public-api.ts
@@ -0,0 +1,2 @@
+export * from './nimble-table-column-icon.directive';
+export * from './nimble-table-column-icon.module';
\ No newline at end of file
diff --git a/angular-workspace/projects/ni/nimble-angular/table-column/icon/tests/nimble-table-column-icon.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/table-column/icon/tests/nimble-table-column-icon.directive.spec.ts
new file mode 100644
index 0000000000..e060362d5f
--- /dev/null
+++ b/angular-workspace/projects/ni/nimble-angular/table-column/icon/tests/nimble-table-column-icon.directive.spec.ts
@@ -0,0 +1,585 @@
+import { Component, ElementRef, ViewChild } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { NimbleTableModule } from '../../../table/nimble-table.module';
+import { NimbleTableColumnIconModule } from '../nimble-table-column-icon.module';
+import { NimbleTableColumnIconDirective, TableColumnIcon } from '../nimble-table-column-icon.directive';
+import { TableColumnSortDirection } from '../../nimble-table-column-base.directive';
+
+describe('NimbleTableColumnIcon', () => {
+ describe('module', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [NimbleTableColumnIconModule]
+ });
+ });
+
+ it('custom element is defined', () => {
+ expect(customElements.get('nimble-table-column-icon')).not.toBeUndefined();
+ });
+ });
+
+ describe('with template string values', () => {
+ @Component({
+ template: `
+
+
+
+ `
+ })
+ class TestHostComponent {
+ @ViewChild('column', { read: NimbleTableColumnIconDirective }) public directive: NimbleTableColumnIconDirective;
+ @ViewChild('column', { read: ElementRef }) public elementRef: ElementRef;
+ }
+
+ let fixture: ComponentFixture;
+ let directive: NimbleTableColumnIconDirective;
+ let nativeElement: TableColumnIcon;
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [TestHostComponent],
+ imports: [NimbleTableColumnIconModule, NimbleTableModule]
+ });
+
+ fixture = TestBed.createComponent(TestHostComponent);
+ fixture.detectChanges();
+ directive = fixture.componentInstance.directive;
+ nativeElement = fixture.componentInstance.elementRef.nativeElement;
+ });
+
+ it('will use template string values for fieldName', () => {
+ expect(directive.fieldName).toBe('field1');
+ expect(nativeElement.fieldName).toBe('field1');
+ });
+
+ it('will use template string values for keyType', () => {
+ expect(directive.keyType).toBe('boolean');
+ expect(nativeElement.keyType).toBe('boolean');
+ });
+
+ it('will use template string values for actionMenuSlot', () => {
+ expect(directive.actionMenuSlot).toBe('my-slot');
+ expect(nativeElement.actionMenuSlot).toBe('my-slot');
+ });
+
+ it('will use template string values for actionMenuLabel', () => {
+ expect(directive.actionMenuLabel).toBe('my menu');
+ expect(nativeElement.actionMenuLabel).toBe('my menu');
+ });
+
+ it('will use template string values for columnId', () => {
+ expect(directive.columnId).toBe('my-column');
+ expect(nativeElement.columnId).toBe('my-column');
+ });
+
+ it('will use template string value for columnHidden', () => {
+ expect(directive.columnHidden).toBe(true);
+ expect(nativeElement.columnHidden).toBe(true);
+ });
+
+ it('will use template string values for sortDirection', () => {
+ expect(directive.sortDirection).toBe(TableColumnSortDirection.ascending);
+ expect(nativeElement.sortDirection).toBe(TableColumnSortDirection.ascending);
+ });
+
+ it('will use template string value for sortIndex', () => {
+ expect(directive.sortIndex).toBe(0);
+ expect(nativeElement.sortIndex).toBe(0);
+ });
+
+ it('will use template string values for fractionalWidth', () => {
+ expect(directive.fractionalWidth).toBe(2);
+ expect(nativeElement.fractionalWidth).toBe(2);
+ });
+
+ it('will use template string values for minPixelWidth', () => {
+ expect(directive.minPixelWidth).toBe(40);
+ expect(nativeElement.minPixelWidth).toBe(40);
+ });
+
+ it('will use template string values for groupIndex', () => {
+ expect(directive.groupIndex).toBe(0);
+ expect(nativeElement.groupIndex).toBe(0);
+ });
+
+ it('will use template string values for groupingDisabled', () => {
+ expect(directive.groupingDisabled).toBeTrue();
+ expect(nativeElement.groupingDisabled).toBeTrue();
+ });
+ });
+
+ describe('with property bound values', () => {
+ @Component({
+ template: `
+
+
+
+ `
+ })
+ class TestHostComponent {
+ @ViewChild('column', { read: NimbleTableColumnIconDirective }) public directive: NimbleTableColumnIconDirective;
+ @ViewChild('column', { read: ElementRef }) public elementRef: ElementRef;
+ public field = 'field1';
+ public keyType = 'boolean';
+ public actionMenuSlot = 'my-slot';
+ public actionMenuLabel = 'my menu';
+ public fractionalWidth: number | null = 2;
+ public minPixelWidth: number | null = 40;
+ public columnId = 'my-column';
+ public columnHidden = true;
+ public sortDirection: TableColumnSortDirection = TableColumnSortDirection.ascending;
+ public sortIndex: number | null = 0;
+ public groupIndex: number | null = 0;
+ public groupingDisabled = false;
+ }
+
+ let fixture: ComponentFixture;
+ let directive: NimbleTableColumnIconDirective;
+ let nativeElement: TableColumnIcon;
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [TestHostComponent],
+ imports: [NimbleTableColumnIconModule, NimbleTableModule]
+ });
+
+ fixture = TestBed.createComponent(TestHostComponent);
+ fixture.detectChanges();
+ directive = fixture.componentInstance.directive;
+ nativeElement = fixture.componentInstance.elementRef.nativeElement;
+ });
+
+ it('can be configured with property binding for fieldName', () => {
+ expect(directive.fieldName).toBe('field1');
+ expect(nativeElement.fieldName).toBe('field1');
+
+ fixture.componentInstance.field = 'field2';
+ fixture.detectChanges();
+
+ expect(directive.fieldName).toBe('field2');
+ expect(nativeElement.fieldName).toBe('field2');
+ });
+
+ it('can be configured with property binding for keyType', () => {
+ expect(directive.keyType).toBe('boolean');
+ expect(nativeElement.keyType).toBe('boolean');
+
+ fixture.componentInstance.keyType = 'number';
+ fixture.detectChanges();
+
+ expect(directive.keyType).toBe('number');
+ expect(nativeElement.keyType).toBe('number');
+ });
+
+ it('can be configured with property binding for actionMenuSlot', () => {
+ expect(directive.actionMenuSlot).toBe('my-slot');
+ expect(nativeElement.actionMenuSlot).toBe('my-slot');
+
+ fixture.componentInstance.actionMenuSlot = 'new-slot';
+ fixture.detectChanges();
+
+ expect(directive.actionMenuSlot).toBe('new-slot');
+ expect(nativeElement.actionMenuSlot).toBe('new-slot');
+ });
+
+ it('can be configured with property binding for actionMenuLabel', () => {
+ expect(directive.actionMenuLabel).toBe('my menu');
+ expect(nativeElement.actionMenuLabel).toBe('my menu');
+
+ fixture.componentInstance.actionMenuLabel = 'another menu';
+ fixture.detectChanges();
+
+ expect(directive.actionMenuLabel).toBe('another menu');
+ expect(nativeElement.actionMenuLabel).toBe('another menu');
+ });
+
+ it('can be configured with property binding for columnId', () => {
+ expect(directive.columnId).toBe('my-column');
+ expect(nativeElement.columnId).toBe('my-column');
+
+ fixture.componentInstance.columnId = 'new-column';
+ fixture.detectChanges();
+
+ expect(directive.columnId).toBe('new-column');
+ expect(nativeElement.columnId).toBe('new-column');
+ });
+
+ it('can be configured with property binding for columnHidden', () => {
+ expect(directive.columnHidden).toBe(true);
+ expect(nativeElement.columnHidden).toBe(true);
+
+ fixture.componentInstance.columnHidden = false;
+ fixture.detectChanges();
+
+ expect(directive.columnHidden).toBe(false);
+ expect(nativeElement.columnHidden).toBe(false);
+ });
+
+ it('can be configured with property binding for sortDirection', () => {
+ expect(directive.sortDirection).toBe(TableColumnSortDirection.ascending);
+ expect(nativeElement.sortDirection).toBe(TableColumnSortDirection.ascending);
+
+ fixture.componentInstance.sortDirection = TableColumnSortDirection.descending;
+ fixture.detectChanges();
+
+ expect(directive.sortDirection).toBe(TableColumnSortDirection.descending);
+ expect(nativeElement.sortDirection).toBe(TableColumnSortDirection.descending);
+ });
+
+ it('can be configured with property binding for sortIndex', () => {
+ expect(directive.sortIndex).toBe(0);
+ expect(nativeElement.sortIndex).toBe(0);
+
+ fixture.componentInstance.sortIndex = 1;
+ fixture.detectChanges();
+
+ expect(directive.sortIndex).toBe(1);
+ expect(nativeElement.sortIndex).toBe(1);
+ });
+
+ it('can be configured with property binding for sortIndex updated to null', () => {
+ expect(directive.sortIndex).toBe(0);
+ expect(nativeElement.sortIndex).toBe(0);
+
+ fixture.componentInstance.sortIndex = null;
+ fixture.detectChanges();
+
+ expect(directive.sortIndex).toBe(null);
+ expect(nativeElement.sortIndex).toBe(null);
+ });
+
+ it('can be configured with property binding for fractionalWidth', () => {
+ expect(directive.fractionalWidth).toBe(2);
+ expect(nativeElement.fractionalWidth).toBe(2);
+
+ fixture.componentInstance.fractionalWidth = 1;
+ fixture.detectChanges();
+
+ expect(directive.fractionalWidth).toBe(1);
+ expect(nativeElement.fractionalWidth).toBe(1);
+ });
+
+ it('can be configured with property binding for fractionalWidth updated to null', () => {
+ expect(directive.fractionalWidth).toBe(2);
+ expect(nativeElement.fractionalWidth).toBe(2);
+
+ fixture.componentInstance.fractionalWidth = null;
+ fixture.detectChanges();
+
+ expect(directive.fractionalWidth).toBe(null);
+ expect(nativeElement.fractionalWidth).toBe(null);
+ });
+
+ it('can be configured with property binding for minPixelWidth', () => {
+ expect(directive.minPixelWidth).toBe(40);
+ expect(nativeElement.minPixelWidth).toBe(40);
+
+ fixture.componentInstance.minPixelWidth = 50;
+ fixture.detectChanges();
+
+ expect(directive.minPixelWidth).toBe(50);
+ expect(nativeElement.minPixelWidth).toBe(50);
+ });
+
+ it('can be configured with property binding for minPixelWidth updated to null', () => {
+ expect(directive.minPixelWidth).toBe(40);
+ expect(nativeElement.minPixelWidth).toBe(40);
+
+ fixture.componentInstance.minPixelWidth = null;
+ fixture.detectChanges();
+
+ expect(directive.minPixelWidth).toBe(null);
+ expect(nativeElement.minPixelWidth).toBe(null);
+ });
+
+ it('can be configured with property binding for groupIndex', () => {
+ expect(directive.groupIndex).toBe(0);
+ expect(nativeElement.groupIndex).toBe(0);
+
+ fixture.componentInstance.groupIndex = 1;
+ fixture.detectChanges();
+
+ expect(directive.groupIndex).toBe(1);
+ expect(nativeElement.groupIndex).toBe(1);
+ });
+
+ it('can be configured with property binding for groupIndex updated to null', () => {
+ expect(directive.groupIndex).toBe(0);
+ expect(nativeElement.groupIndex).toBe(0);
+
+ fixture.componentInstance.groupIndex = null;
+ fixture.detectChanges();
+
+ expect(directive.groupIndex).toBe(null);
+ expect(nativeElement.groupIndex).toBe(null);
+ });
+
+ it('can be configured with property binding for groupingDisabled', () => {
+ expect(directive.groupingDisabled).toBeFalse();
+ expect(nativeElement.groupingDisabled).toBeFalse();
+
+ fixture.componentInstance.groupingDisabled = true;
+ fixture.detectChanges();
+
+ expect(directive.groupingDisabled).toBeTrue();
+ expect(nativeElement.groupingDisabled).toBeTrue();
+ });
+ });
+
+ describe('with attribute bound values', () => {
+ @Component({
+ template: `
+
+
+
+ `
+ })
+ class TestHostComponent {
+ @ViewChild('column', { read: NimbleTableColumnIconDirective }) public directive: NimbleTableColumnIconDirective;
+ @ViewChild('column', { read: ElementRef }) public elementRef: ElementRef;
+ public field = 'field1';
+ public keyType = 'boolean';
+ public actionMenuSlot = 'my-slot';
+ public actionMenuLabel = 'my menu';
+ public fractionalWidth: number | null = 2;
+ public minPixelWidth: number | null = 40;
+ public columnId = 'my-column';
+ public columnHidden = true;
+ public sortDirection: TableColumnSortDirection = TableColumnSortDirection.ascending;
+ public sortIndex: number | null = 0;
+ public groupIndex: number | null = 0;
+ public groupingDisabled = false;
+ }
+
+ let fixture: ComponentFixture;
+ let directive: NimbleTableColumnIconDirective;
+ let nativeElement: TableColumnIcon;
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [TestHostComponent],
+ imports: [NimbleTableColumnIconModule, NimbleTableModule]
+ });
+
+ fixture = TestBed.createComponent(TestHostComponent);
+ fixture.detectChanges();
+ directive = fixture.componentInstance.directive;
+ nativeElement = fixture.componentInstance.elementRef.nativeElement;
+ });
+
+ it('can be configured with attribute binding for fieldName', () => {
+ expect(directive.fieldName).toBe('field1');
+ expect(nativeElement.fieldName).toBe('field1');
+
+ fixture.componentInstance.field = 'field2';
+ fixture.detectChanges();
+
+ expect(directive.fieldName).toBe('field2');
+ expect(nativeElement.fieldName).toBe('field2');
+ });
+
+ it('can be configured with attribute binding for keyType', () => {
+ expect(directive.keyType).toBe('boolean');
+ expect(nativeElement.keyType).toBe('boolean');
+
+ fixture.componentInstance.keyType = 'number';
+ fixture.detectChanges();
+
+ expect(directive.keyType).toBe('number');
+ expect(nativeElement.keyType).toBe('number');
+ });
+
+ it('can be configured with attribute binding for actionMenuSlot', () => {
+ expect(directive.actionMenuSlot).toBe('my-slot');
+ expect(nativeElement.actionMenuSlot).toBe('my-slot');
+
+ fixture.componentInstance.actionMenuSlot = 'new-slot';
+ fixture.detectChanges();
+
+ expect(directive.actionMenuSlot).toBe('new-slot');
+ expect(nativeElement.actionMenuSlot).toBe('new-slot');
+ });
+
+ it('can be configured with attribute binding for actionMenuLabel', () => {
+ expect(directive.actionMenuLabel).toBe('my menu');
+ expect(nativeElement.actionMenuLabel).toBe('my menu');
+
+ fixture.componentInstance.actionMenuLabel = 'another menu';
+ fixture.detectChanges();
+
+ expect(directive.actionMenuLabel).toBe('another menu');
+ expect(nativeElement.actionMenuLabel).toBe('another menu');
+ });
+
+ it('can be configured with attribute binding for columnId', () => {
+ expect(directive.columnId).toBe('my-column');
+ expect(nativeElement.columnId).toBe('my-column');
+
+ fixture.componentInstance.columnId = 'new-column';
+ fixture.detectChanges();
+
+ expect(directive.columnId).toBe('new-column');
+ expect(nativeElement.columnId).toBe('new-column');
+ });
+
+ it('can be configured with attribute binding for columnHidden', () => {
+ expect(directive.columnHidden).toBe(true);
+ expect(nativeElement.columnHidden).toBe(true);
+
+ fixture.componentInstance.columnHidden = false;
+ fixture.detectChanges();
+
+ expect(directive.columnHidden).toBe(false);
+ expect(nativeElement.columnHidden).toBe(false);
+ });
+
+ it('can be configured with attribute binding for sortDirection', () => {
+ expect(directive.sortDirection).toBe(TableColumnSortDirection.ascending);
+ expect(nativeElement.sortDirection).toBe(TableColumnSortDirection.ascending);
+
+ fixture.componentInstance.sortDirection = TableColumnSortDirection.descending;
+ fixture.detectChanges();
+
+ expect(directive.sortDirection).toBe(TableColumnSortDirection.descending);
+ expect(nativeElement.sortDirection).toBe(TableColumnSortDirection.descending);
+ });
+
+ it('can be configured with attribute binding for sortIndex', () => {
+ expect(directive.sortIndex).toBe(0);
+ expect(nativeElement.sortIndex).toBe(0);
+
+ fixture.componentInstance.sortIndex = 1;
+ fixture.detectChanges();
+
+ expect(directive.sortIndex).toBe(1);
+ expect(nativeElement.sortIndex).toBe(1);
+ });
+
+ it('can be configured with attribute binding for sortIndex updated to null', () => {
+ expect(directive.sortIndex).toBe(0);
+ expect(nativeElement.sortIndex).toBe(0);
+
+ fixture.componentInstance.sortIndex = null;
+ fixture.detectChanges();
+
+ expect(directive.sortIndex).toBe(null);
+ expect(nativeElement.sortIndex).toBe(null);
+ });
+
+ it('can be configured with attribute binding for fractionalWidth', () => {
+ expect(directive.fractionalWidth).toBe(2);
+ expect(nativeElement.fractionalWidth).toBe(2);
+
+ fixture.componentInstance.fractionalWidth = 1;
+ fixture.detectChanges();
+
+ expect(directive.fractionalWidth).toBe(1);
+ expect(nativeElement.fractionalWidth).toBe(1);
+ });
+
+ it('can be configured with attribute binding for fractionalWidth set to null', () => {
+ expect(directive.fractionalWidth).toBe(2);
+ expect(nativeElement.fractionalWidth).toBe(2);
+
+ fixture.componentInstance.fractionalWidth = null;
+ fixture.detectChanges();
+
+ expect(directive.fractionalWidth).toBe(null);
+ expect(nativeElement.fractionalWidth).toBe(null);
+ });
+
+ it('can be configured with attribute binding for minPixelWidth', () => {
+ expect(directive.minPixelWidth).toBe(40);
+ expect(nativeElement.minPixelWidth).toBe(40);
+
+ fixture.componentInstance.minPixelWidth = 50;
+ fixture.detectChanges();
+
+ expect(directive.minPixelWidth).toBe(50);
+ expect(nativeElement.minPixelWidth).toBe(50);
+ });
+
+ it('can be configured with attribute binding for minPixelWidth set to null', () => {
+ expect(directive.minPixelWidth).toBe(40);
+ expect(nativeElement.minPixelWidth).toBe(40);
+
+ fixture.componentInstance.minPixelWidth = null;
+ fixture.detectChanges();
+
+ expect(directive.minPixelWidth).toBe(null);
+ expect(nativeElement.minPixelWidth).toBe(null);
+ });
+
+ it('can be configured with attribute binding for groupIndex', () => {
+ expect(directive.groupIndex).toBe(0);
+ expect(nativeElement.groupIndex).toBe(0);
+
+ fixture.componentInstance.groupIndex = 1;
+ fixture.detectChanges();
+
+ expect(directive.groupIndex).toBe(1);
+ expect(nativeElement.groupIndex).toBe(1);
+ });
+
+ it('can be configured with attribute binding for groupIndex updated to null', () => {
+ expect(directive.groupIndex).toBe(0);
+ expect(nativeElement.groupIndex).toBe(0);
+
+ fixture.componentInstance.groupIndex = null;
+ fixture.detectChanges();
+
+ expect(directive.groupIndex).toBe(null);
+ expect(nativeElement.groupIndex).toBe(null);
+ });
+
+ it('can be configured with attribute binding for groupingDisabled', () => {
+ expect(directive.groupingDisabled).toBe(false);
+ expect(nativeElement.groupingDisabled).toBe(false);
+
+ fixture.componentInstance.groupingDisabled = true;
+ fixture.detectChanges();
+
+ expect(directive.groupingDisabled).toBe(true);
+ expect(nativeElement.groupingDisabled).toBe(true);
+ });
+ });
+});
\ No newline at end of file
diff --git a/change/@ni-nimble-angular-5a38f8f9-f799-46ba-8981-eb3e4c3ff9f8.json b/change/@ni-nimble-angular-5a38f8f9-f799-46ba-8981-eb3e4c3ff9f8.json
new file mode 100644
index 0000000000..2a2ed43e38
--- /dev/null
+++ b/change/@ni-nimble-angular-5a38f8f9-f799-46ba-8981-eb3e4c3ff9f8.json
@@ -0,0 +1,7 @@
+{
+ "type": "patch",
+ "comment": "Angular support for icon table column",
+ "packageName": "@ni/nimble-angular",
+ "email": "7282195+m-akinc@users.noreply.github.com",
+ "dependentChangeType": "patch"
+}