Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Angular integration for nimble-chip component",
"packageName": "@ni/nimble-angular",
"email": "123377523+vivinkrishna-ni@users.noreply.github.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { NimbleTextAreaModule, NimbleTextFieldModule, NimbleNumberFieldModule, N
NimbleIconCheckModule, NimbleBannerModule, NimbleAnchorMenuItemModule, NimbleAnchorTreeItemModule, NimbleIconXmarkCheckModule,
NimbleListOptionGroupModule } from '@ni/nimble-angular';
import { NimbleCardModule } from '@ni/nimble-angular/card';
import { NimbleChipModule } from '@ni/nimble-angular/chip';
import { NimbleLabelProviderCoreModule } from '@ni/nimble-angular/label-provider/core';
import { NimbleLabelProviderRichTextModule } from '@ni/nimble-angular/label-provider/rich-text';
import { NimbleLabelProviderTableModule } from '@ni/nimble-angular/label-provider/table';
Expand Down Expand Up @@ -70,6 +71,7 @@ import { CustomAppComponent } from './customapp/customapp.component';
NimbleTabsToolbarModule,
NimbleDrawerModule,
NimbleCheckboxModule,
NimbleChipModule,
NimbleToggleButtonModule,
NimbleBreadcrumbModule,
NimbleBreadcrumbItemModule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@
<nimble-checkbox>Checkbox label</nimble-checkbox>
<nimble-checkbox>Checkbox label</nimble-checkbox>
</div>
<div class="sub-container">
Comment thread
vivinkrishna-ni marked this conversation as resolved.
<div class="container-label">Chip</div>
<nimble-chip>Outline Chip</nimble-chip>
<nimble-chip appearance="block">Block Chip</nimble-chip>
<nimble-chip removable (remove)="onChipRemove()">Removable Chip</nimble-chip>
<nimble-chip disabled>Disabled Chip</nimble-chip>
</div>
<div class="sub-container">
<div class="container-label">Radio Buttons</div>
<nimble-radio-group>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ export class CustomAppComponent implements AfterViewInit {
alert(`${menuItemText} selected`);
}

public onChipRemove(): void {
alert('Chip removed');
}

public onDynamicSelectFilterInput(e: Event): void {
const event = e as CustomEvent<SelectFilterInputEventDetail>;
const filter = event.detail.filterText;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema": "../../../../node_modules/ng-packagr/ng-package.schema.json",
"lib": {
"entryFile": "public-api.ts"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Directive, ElementRef, Input, Renderer2 } from '@angular/core';
import { type Chip, chipTag } from '@ni/nimble-components/dist/esm/chip';
import { ChipAppearance } from '@ni/nimble-components/dist/esm/chip/types';
import { type BooleanValueOrAttribute, toBooleanProperty } from '@ni/nimble-angular/internal-utilities';

export type { Chip };
export { chipTag };
export { ChipAppearance };

/**
* Directive to provide Angular integration for the chip.
*/
@Directive({
selector: 'nimble-chip',
standalone: false
})
export class NimbleChipDirective {
public get removable(): boolean {
return this.elementRef.nativeElement.removable;
}

@Input() public set removable(value: BooleanValueOrAttribute) {
this.renderer.setProperty(this.elementRef.nativeElement, 'removable', toBooleanProperty(value));
}

public get disabled(): boolean {
return this.elementRef.nativeElement.disabled;
}

@Input() public set disabled(value: BooleanValueOrAttribute) {
this.renderer.setProperty(this.elementRef.nativeElement, 'disabled', toBooleanProperty(value));
}

public get appearance(): ChipAppearance {
return this.elementRef.nativeElement.appearance;
}

@Input() public set appearance(value: ChipAppearance) {
this.renderer.setProperty(this.elementRef.nativeElement, 'appearance', value);
}

public constructor(private readonly renderer: Renderer2, private readonly elementRef: ElementRef<Chip>) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NimbleChipDirective } from './nimble-chip.directive';

import '@ni/nimble-components/dist/esm/chip';

@NgModule({
declarations: [NimbleChipDirective],
imports: [CommonModule],
exports: [NimbleChipDirective]
})
export class NimbleChipModule { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './nimble-chip.directive';
export * from './nimble-chip.module';
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { ChipPageObject } from '@ni/nimble-components/dist/esm/chip/testing/chip.pageobject';

export { ChipPageObject };
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema": "../../../../../node_modules/ng-packagr/ng-package.schema.json",
"lib": {
"entryFile": "public-api.ts"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { ChipPageObject } from './chip.pageobject';
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
import { Component, ElementRef, ViewChild } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import type { BooleanValueOrAttribute } from '@ni/nimble-angular/internal-utilities';
import { type Chip, ChipAppearance, NimbleChipDirective } from '../nimble-chip.directive';
import { NimbleChipModule } from '../nimble-chip.module';

describe('Nimble chip', () => {
describe('module', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [NimbleChipModule]
});
});

it('custom element is defined', () => {
expect(customElements.get('nimble-chip')).not.toBeUndefined();
});
});

describe('with no values in template', () => {
@Component({
template: `
<nimble-chip #chip></nimble-chip>
`,
standalone: false
})
class TestHostComponent {
@ViewChild('chip', { read: NimbleChipDirective }) public directive: NimbleChipDirective;
@ViewChild('chip', { read: ElementRef }) public elementRef: ElementRef<Chip>;
}

let fixture: ComponentFixture<TestHostComponent>;
let directive: NimbleChipDirective;
let nativeElement: Chip;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TestHostComponent],
imports: [NimbleChipModule]
});
fixture = TestBed.createComponent(TestHostComponent);
fixture.detectChanges();
directive = fixture.componentInstance.directive;
nativeElement = fixture.componentInstance.elementRef.nativeElement;
});

it('has expected defaults for removable', () => {
expect(directive.removable).toBeFalse();
expect(nativeElement.removable).toBeFalse();
});

it('has expected defaults for disabled', () => {
expect(directive.disabled).toBeFalse();
expect(nativeElement.disabled).toBeFalse();
});

it('has expected defaults for appearance', () => {
expect(directive.appearance).toBe(ChipAppearance.outline);
expect(nativeElement.appearance).toBe(ChipAppearance.outline);
});
});

describe('with template string values', () => {
@Component({
template: `
<nimble-chip #chip
removable
disabled
appearance="block">
</nimble-chip>`,
standalone: false
})
class TestHostComponent {
@ViewChild('chip', { read: NimbleChipDirective }) public directive: NimbleChipDirective;
@ViewChild('chip', { read: ElementRef }) public elementRef: ElementRef<Chip>;
}

let fixture: ComponentFixture<TestHostComponent>;
let directive: NimbleChipDirective;
let nativeElement: Chip;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TestHostComponent],
imports: [NimbleChipModule]
});
fixture = TestBed.createComponent(TestHostComponent);
fixture.detectChanges();
directive = fixture.componentInstance.directive;
nativeElement = fixture.componentInstance.elementRef.nativeElement;
});

it('will use template string values for removable', () => {
expect(directive.removable).toBeTrue();
expect(nativeElement.removable).toBeTrue();
});

it('will use template string values for disabled', () => {
expect(directive.disabled).toBeTrue();
expect(nativeElement.disabled).toBeTrue();
});

it('will use template string values for appearance', () => {
expect(directive.appearance).toBe(ChipAppearance.block);
expect(nativeElement.appearance).toBe(ChipAppearance.block);
});
});

describe('with property bound values', () => {
@Component({
template: `
<nimble-chip #chip
[removable]="removable"
[disabled]="disabled"
[appearance]="appearance">
</nimble-chip>
`,
standalone: false
})
class TestHostComponent {
@ViewChild('chip', { read: NimbleChipDirective }) public directive: NimbleChipDirective;
@ViewChild('chip', { read: ElementRef }) public elementRef: ElementRef<Chip>;
public removable = false;
public disabled = false;
public appearance: ChipAppearance = ChipAppearance.outline;
}

let fixture: ComponentFixture<TestHostComponent>;
let directive: NimbleChipDirective;
let nativeElement: Chip;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TestHostComponent],
imports: [NimbleChipModule]
});
fixture = TestBed.createComponent(TestHostComponent);
fixture.detectChanges();
directive = fixture.componentInstance.directive;
nativeElement = fixture.componentInstance.elementRef.nativeElement;
});

it('can be configured with property binding for removable', () => {
expect(directive.removable).toBeFalse();
expect(nativeElement.removable).toBeFalse();

fixture.componentInstance.removable = true;
fixture.detectChanges();

expect(directive.removable).toBeTrue();
expect(nativeElement.removable).toBeTrue();
});

it('can be configured with property binding for disabled', () => {
expect(directive.disabled).toBeFalse();
expect(nativeElement.disabled).toBeFalse();

fixture.componentInstance.disabled = true;
fixture.detectChanges();

expect(directive.disabled).toBeTrue();
expect(nativeElement.disabled).toBeTrue();
});

it('can be configured with property binding for appearance', () => {
expect(directive.appearance).toBe(ChipAppearance.outline);
expect(nativeElement.appearance).toBe(ChipAppearance.outline);

fixture.componentInstance.appearance = ChipAppearance.block;
fixture.detectChanges();

expect(directive.appearance).toBe(ChipAppearance.block);
expect(nativeElement.appearance).toBe(ChipAppearance.block);
});
});

describe('with attribute bound values', () => {
@Component({
template: `
<nimble-chip #chip
[attr.removable]="removable"
[attr.disabled]="disabled"
[attr.appearance]="appearance">
</nimble-chip>
`,
standalone: false
})
class TestHostComponent {
@ViewChild('chip', { read: NimbleChipDirective }) public directive: NimbleChipDirective;
@ViewChild('chip', { read: ElementRef }) public elementRef: ElementRef<Chip>;
public removable: BooleanValueOrAttribute = null;
public disabled: BooleanValueOrAttribute = null;
public appearance: ChipAppearance = ChipAppearance.outline;
}

let fixture: ComponentFixture<TestHostComponent>;
let directive: NimbleChipDirective;
let nativeElement: Chip;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TestHostComponent],
imports: [NimbleChipModule]
});
fixture = TestBed.createComponent(TestHostComponent);
fixture.detectChanges();
directive = fixture.componentInstance.directive;
nativeElement = fixture.componentInstance.elementRef.nativeElement;
});

it('can be configured with attribute binding for removable', () => {
expect(directive.removable).toBeFalse();
expect(nativeElement.removable).toBeFalse();

fixture.componentInstance.removable = '';
fixture.detectChanges();

expect(directive.removable).toBeTrue();
expect(nativeElement.removable).toBeTrue();
});

it('can be configured with attribute binding for disabled', () => {
expect(directive.disabled).toBeFalse();
expect(nativeElement.disabled).toBeFalse();

fixture.componentInstance.disabled = '';
fixture.detectChanges();

expect(directive.disabled).toBeTrue();
expect(nativeElement.disabled).toBeTrue();
});

it('can be configured with attribute binding for appearance', () => {
expect(directive.appearance).toBe(ChipAppearance.outline);
expect(nativeElement.appearance).toBe(ChipAppearance.outline);

fixture.componentInstance.appearance = ChipAppearance.block;
fixture.detectChanges();

expect(directive.appearance).toBe(ChipAppearance.block);
expect(nativeElement.appearance).toBe(ChipAppearance.block);
});
});
});
2 changes: 1 addition & 1 deletion packages/storybook/src/docs/component-status.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ const components = [
designLabel: 'Figma',
library: 'nimble',
componentStatus: ComponentFrameworkStatus.ready,
angularStatus: ComponentFrameworkStatus.doesNotExist,
angularStatus: ComponentFrameworkStatus.ready,
blazorStatus: ComponentFrameworkStatus.doesNotExist
},
{
Expand Down