diff --git a/apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/advanced/demo.component.html b/apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/advanced/demo.component.html
deleted file mode 100644
index 004bf43632..0000000000
--- a/apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/advanced/demo.component.html
+++ /dev/null
@@ -1,150 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ node.data.name }}
-
-
-
-
-
-
-
-
-
diff --git a/apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/advanced/demo.component.ts b/apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/advanced/demo.component.ts
deleted file mode 100644
index 02101d9689..0000000000
--- a/apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/advanced/demo.component.ts
+++ /dev/null
@@ -1,234 +0,0 @@
-import { CommonModule } from '@angular/common';
-import {
- ChangeDetectionStrategy,
- ChangeDetectorRef,
- Component,
- OnDestroy,
- OnInit,
- ViewChild,
- inject,
-} from '@angular/core';
-import {
- FormBuilder,
- FormControl,
- FormGroup,
- ReactiveFormsModule,
-} from '@angular/forms';
-import {
- ITreeOptions,
- ITreeState,
- TreeModel,
- TreeModule,
- TreeNode,
-} from '@blackbaud/angular-tree-component';
-import { SkyAngularTreeModule } from '@skyux/angular-tree-component';
-import { SkyCheckboxModule, SkyRadioModule } from '@skyux/forms';
-import { SkyFluidGridModule, SkyFormatModule } from '@skyux/layout';
-import { SkyDropdownModule } from '@skyux/popovers';
-
-import { Subject, takeUntil } from 'rxjs';
-
-import { AngularTreeDemoNode } from './node';
-
-@Component({
- standalone: true,
- selector: 'app-demo',
- templateUrl: './demo.component.html',
- changeDetection: ChangeDetectionStrategy.OnPush,
- imports: [
- CommonModule,
- ReactiveFormsModule,
- SkyAngularTreeModule,
- SkyCheckboxModule,
- SkyDropdownModule,
- SkyFluidGridModule,
- SkyFormatModule,
- SkyRadioModule,
- TreeModule,
- ],
-})
-export class DemoComponent implements OnInit, OnDestroy {
- protected set enableCascading(value: boolean) {
- this.#resetSelection();
- this.treeOptions.useTriState = value;
- this.#_enableCascading = value;
-
- if (value) {
- this.selectLeafNodesOnly = false;
- }
- }
-
- protected get enableCascading(): boolean {
- return this.#_enableCascading;
- }
-
- protected set selectLeafNodesOnly(value: boolean) {
- this.#resetSelection();
- this.#_selectLeafNodesOnly = value;
-
- if (value) {
- this.enableCascading = false;
- }
- }
-
- protected get selectLeafNodesOnly(): boolean {
- return this.#_selectLeafNodesOnly;
- }
-
- protected formGroup: FormGroup;
-
- protected dropdownItems: { name: string; disabled: boolean }[] = [
- {
- name: 'Insert an item adjacent to {0}',
- disabled: false,
- },
- { name: 'Insert an item under {0}', disabled: false },
- { name: 'Move up {0}', disabled: false },
- { name: 'Move down {0}', disabled: false },
- { name: 'Move left {0}', disabled: false },
- { name: 'Move right {0}', disabled: false },
- { name: 'Edit {0}', disabled: false },
- { name: 'Delete {0}', disabled: false },
- ];
-
- protected nodes: AngularTreeDemoNode[] = [
- {
- name: 'Animals',
- isExpanded: true,
- children: [
- {
- name: 'Cats',
- isExpanded: true,
- children: [
- { name: 'Burmese' },
- { name: 'Persian' },
- { name: 'Tabby' },
- ],
- },
- {
- name: 'Dogs',
- isExpanded: true,
- children: [
- { name: 'Beagle' },
- { name: 'German shepherd' },
- { name: 'Labrador retriever' },
- ],
- },
- ],
- },
- ];
-
- protected readOnly = false;
- protected selectSingle = false;
- protected treeOptions: ITreeOptions = {
- animateExpand: true,
- useTriState: false,
- };
-
- @ViewChild(TreeModel)
- private tree: TreeModel | undefined;
-
- #_enableCascading = false;
- #_selectLeafNodesOnly = false;
-
- #ngUnsubscribe = new Subject();
-
- readonly #changeDetectorRef = inject(ChangeDetectorRef);
-
- constructor() {
- this.formGroup = inject(FormBuilder).group({
- treeMode: new FormControl('navigation'),
- selectMode: new FormControl('multiSelect'),
- selectLeafNodesOnly: new FormControl(),
- enableCascading: new FormControl(),
- showToolbar: new FormControl(),
- showContextMenus: new FormControl(),
- });
- }
-
- public ngOnInit(): void {
- this.formGroup.valueChanges
- .pipe(takeUntil(this.#ngUnsubscribe))
- .subscribe((value) => {
- if (value.treeMode) {
- switch (value.treeMode) {
- case 'selection':
- this.readOnly = false;
- this.#enableSelection(true);
- break;
-
- case 'readOnly':
- this.readOnly = true;
- this.#enableSelection(false);
- break;
-
- case 'navigation':
- this.readOnly = false;
- this.#enableSelection(false);
- break;
-
- default:
- break;
- }
- }
-
- if (value.selectMode) {
- switch (value.selectMode) {
- case 'singleSelect':
- this.#resetSelection();
- this.selectSingle = true;
- this.enableCascading = false;
- break;
-
- case 'multiSelect':
- this.#resetSelection();
- this.selectSingle = false;
- this.enableCascading = false;
- break;
-
- default:
- break;
- }
- }
-
- if (value.enableCascading) {
- this.enableCascading = value.enableCascading;
- }
-
- if (value.selectLeafNodesOnly) {
- this.selectLeafNodesOnly = value.selectLeafNodesOnly;
- }
-
- this.#changeDetectorRef.markForCheck();
- });
- }
-
- public ngOnDestroy(): void {
- this.#ngUnsubscribe.next();
- this.#ngUnsubscribe.complete();
- }
-
- protected actionClicked(name: string, node: TreeNode): void {
- // Add custom actions here.
- alert(name.replace('{0}', node.data.name) + ' clicked!');
- }
-
- protected onTreeStateChange(treeModel: ITreeState): void {
- // Watch for tree state changes here.
- console.log(treeModel);
- }
-
- #enableSelection(value: boolean): void {
- this.#resetSelection();
- this.treeOptions.useCheckbox = value;
- this.selectLeafNodesOnly = false;
- this.enableCascading = false;
- }
-
- #resetSelection(): void {
- if (this.tree) {
- this.tree.selectedLeafNodeIds = {};
- this.tree.activeNodeIds = {};
- }
- }
-}
diff --git a/apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/advanced/node.ts b/apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/advanced/node.ts
deleted file mode 100644
index cb4d1f6dce..0000000000
--- a/apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/advanced/node.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export interface AngularTreeDemoNode {
- name: string;
- isExpanded?: boolean;
- children?: AngularTreeDemoNode[];
-}
diff --git a/apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/inline-help/demo.component.html b/apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/basic/demo.component.html
similarity index 58%
rename from apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/inline-help/demo.component.html
rename to apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/basic/demo.component.html
index 48b1a7e305..99a19eadfe 100644
--- a/apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/inline-help/demo.component.html
+++ b/apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/basic/demo.component.html
@@ -7,17 +7,12 @@
#treeNodeFullTemplate
>
-
-
+ />
diff --git a/apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/inline-help/demo.component.ts b/apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/basic/demo.component.ts
similarity index 82%
rename from apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/inline-help/demo.component.ts
rename to apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/basic/demo.component.ts
index e44776cf88..1d013ecd86 100644
--- a/apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/inline-help/demo.component.ts
+++ b/apps/code-examples/src/app/code-examples/angular-tree-component/angular-tree/basic/demo.component.ts
@@ -21,12 +21,13 @@ export class DemoComponent {
{
name: 'Animals',
isExpanded: true,
- showHelp: true,
+ helpPopoverContent: 'Example help content for animals.',
children: [
{
name: 'Cats',
isExpanded: true,
- showHelp: true,
+ helpPopoverContent: 'Example help content for cats.',
+ helpPopoverTitle: 'What is a cat?',
children: [
{ name: 'Burmese' },
{ name: 'Persian' },
@@ -39,7 +40,7 @@ export class DemoComponent {
children: [
{
name: 'Beagle',
- showHelp: true,
+ helpPopoverContent: 'Example help content for beagles.',
},
{ name: 'German shepherd' },
{ name: 'Labrador retriever' },
@@ -48,8 +49,4 @@ export class DemoComponent {
],
},
];
-
- protected onActionClick(): void {
- alert('Help inline button clicked!');
- }
}
diff --git a/apps/code-examples/src/app/features/angular-tree.modules.ts b/apps/code-examples/src/app/features/angular-tree.modules.ts
index e8877ae87e..3a298c04c5 100644
--- a/apps/code-examples/src/app/features/angular-tree.modules.ts
+++ b/apps/code-examples/src/app/features/angular-tree.modules.ts
@@ -3,17 +3,10 @@ import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{
- path: 'advanced',
+ path: 'basic',
loadComponent: () =>
import(
- '../code-examples/angular-tree-component/angular-tree/advanced/demo.component'
- ).then((c) => c.DemoComponent),
- },
- {
- path: 'inline-help',
- loadComponent: () =>
- import(
- '../code-examples/angular-tree-component/angular-tree/inline-help/demo.component'
+ '../code-examples/angular-tree-component/angular-tree/basic/demo.component'
).then((c) => c.DemoComponent),
},
];
diff --git a/apps/code-examples/src/app/home/home.component.html b/apps/code-examples/src/app/home/home.component.html
index 793a04d396..9bf85edb6e 100644
--- a/apps/code-examples/src/app/home/home.component.html
+++ b/apps/code-examples/src/app/home/home.component.html
@@ -66,8 +66,7 @@
Angular Tree
diff --git a/apps/e2e/angular-tree-component-storybook/src/app/angular-tree-component/angular-tree-component.component.html b/apps/e2e/angular-tree-component-storybook/src/app/angular-tree-component/angular-tree-component.component.html
index a0596586db..51e5eea6ff 100644
--- a/apps/e2e/angular-tree-component-storybook/src/app/angular-tree-component/angular-tree-component.component.html
+++ b/apps/e2e/angular-tree-component-storybook/src/app/angular-tree-component/angular-tree-component.component.html
@@ -75,4 +75,24 @@ Basic with toolbar, context menu and inline help
+ Basic with easy mode inline help
+
+
+
+
+
+
+
diff --git a/libs/components/angular-tree-component/package.json b/libs/components/angular-tree-component/package.json
index 51658a1656..4730c379d2 100644
--- a/libs/components/angular-tree-component/package.json
+++ b/libs/components/angular-tree-component/package.json
@@ -21,6 +21,7 @@
"@blackbaud/angular-tree-component": "^1.0.0",
"@skyux/core": "0.0.0-PLACEHOLDER",
"@skyux/forms": "0.0.0-PLACEHOLDER",
+ "@skyux/help-inline": "0.0.0-PLACEHOLDER",
"@skyux/i18n": "0.0.0-PLACEHOLDER",
"@skyux/indicators": "0.0.0-PLACEHOLDER",
"@skyux/layout": "0.0.0-PLACEHOLDER"
diff --git a/libs/components/angular-tree-component/src/lib/modules/angular-tree/angular-tree-node.component.html b/libs/components/angular-tree-component/src/lib/modules/angular-tree/angular-tree-node.component.html
index 9d440ebf12..119ee60d9e 100644
--- a/libs/components/angular-tree-component/src/lib/modules/angular-tree/angular-tree-node.component.html
+++ b/libs/components/angular-tree-component/src/lib/modules/angular-tree/angular-tree-node.component.html
@@ -89,9 +89,18 @@
(click)="node.mouseAction('click', $event)"
>
+ >
+ @if (helpKey || helpPopoverContent) {
+
+ } @else {
+
+ }
+
diff --git a/libs/components/angular-tree-component/src/lib/modules/angular-tree/angular-tree-node.component.ts b/libs/components/angular-tree-component/src/lib/modules/angular-tree/angular-tree-node.component.ts
index c3cd476935..22aec63d6e 100644
--- a/libs/components/angular-tree-component/src/lib/modules/angular-tree/angular-tree-node.component.ts
+++ b/libs/components/angular-tree-component/src/lib/modules/angular-tree/angular-tree-node.component.ts
@@ -6,6 +6,7 @@ import {
Input,
OnInit,
Optional,
+ TemplateRef,
ViewChild,
inject,
} from '@angular/core';
@@ -52,6 +53,31 @@ export class SkyAngularTreeNodeComponent implements AfterViewInit, OnInit {
@Input()
public templates: any;
+ /**
+ * A help key that identifies the global help content to display. When specified, a [help inline](https://developer.blackbaud.com/skyux/components/help-inline) button is
+ * placed beside the tree node label. Clicking the button invokes global help as configured by the application.
+ * @preview
+ */
+ @Input()
+ public helpKey: string | undefined;
+
+ /**
+ * The content of the help popover. When specified, a [help inline](https://developer.blackbaud.com/skyux/components/help-inline)
+ * button is added to the tree node. The help inline button displays a [popover](https://developer.blackbaud.com/skyux/components/popover)
+ * when clicked using the specified content and optional title.
+ * @preview
+ */
+ @Input()
+ public helpPopoverContent: string | TemplateRef | undefined;
+
+ /**
+ * The title of the help popover. This property only applies when `helpPopoverContent` is
+ * also specified.
+ * @preview
+ */
+ @Input()
+ public helpPopoverTitle: string | undefined;
+
public set childFocusIndex(value: number | undefined) {
if (value !== this.#_childFocusIndex) {
this.#_childFocusIndex = value;
diff --git a/libs/components/angular-tree-component/src/lib/modules/angular-tree/angular-tree-root.component.spec.ts b/libs/components/angular-tree-component/src/lib/modules/angular-tree/angular-tree-root.component.spec.ts
index 5d687e7983..830aff9aba 100644
--- a/libs/components/angular-tree-component/src/lib/modules/angular-tree/angular-tree-root.component.spec.ts
+++ b/libs/components/angular-tree-component/src/lib/modules/angular-tree/angular-tree-root.component.spec.ts
@@ -6,6 +6,10 @@ import {
tick,
} from '@angular/core/testing';
import { SkyAppTestUtility, expect, expectAsync } from '@skyux-sdk/testing';
+import {
+ SkyHelpTestingController,
+ SkyHelpTestingModule,
+} from '@skyux/core/testing';
import { SkyTreeViewFixtureComponent } from './fixtures/tree-view.fixture.component';
import { SkyTreeViewFixturesModule } from './fixtures/tree-view.fixture.module';
@@ -190,7 +194,7 @@ describe('tree view', () => {
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [SkyTreeViewFixturesModule],
+ imports: [SkyHelpTestingModule, SkyTreeViewFixturesModule],
});
fixture = TestBed.createComponent(
@@ -259,6 +263,30 @@ describe('tree view', () => {
'fa-chevron-right',
);
});
+
+ it('should render help inline popover', () => {
+ component.nodes[0].helpPopoverContent = 'Example popover content.';
+ component.nodes[0].helpPopoverTitle = 'Example popover title';
+
+ fixture.detectChanges();
+
+ expect(
+ fixture.nativeElement.querySelectorAll(
+ 'sky-help-inline:not(.sky-control-help)',
+ ).length,
+ ).toBe(1);
+ });
+
+ it('should render help inline when helpKey is provided', () => {
+ const helpController = TestBed.inject(SkyHelpTestingController);
+ component.nodes[0].helpKey = 'foo.html';
+ fixture.detectChanges();
+
+ fixture.nativeElement.querySelector('.sky-help-inline')?.click();
+ fixture.detectChanges();
+
+ helpController.expectCurrentHelpKey('foo.html');
+ });
});
describe('toolbar', () => {
diff --git a/libs/components/angular-tree-component/src/lib/modules/angular-tree/angular-tree.module.ts b/libs/components/angular-tree-component/src/lib/modules/angular-tree/angular-tree.module.ts
index 77613a3a77..8898513719 100644
--- a/libs/components/angular-tree-component/src/lib/modules/angular-tree/angular-tree.module.ts
+++ b/libs/components/angular-tree-component/src/lib/modules/angular-tree/angular-tree.module.ts
@@ -3,6 +3,7 @@ import { NgModule } from '@angular/core';
import { TreeModule } from '@blackbaud/angular-tree-component';
import { SkyCoreAdapterService } from '@skyux/core';
import { SkyCheckboxModule } from '@skyux/forms';
+import { SkyHelpInlineModule } from '@skyux/help-inline';
import { SkyIconModule } from '@skyux/indicators';
import { SkyToolbarModule } from '@skyux/layout';
@@ -24,6 +25,7 @@ import { SkyAngularTreeWrapperComponent } from './angular-tree-wrapper.component
CommonModule,
SkyAngularTreeComponentResourcesModule,
SkyCheckboxModule,
+ SkyHelpInlineModule,
SkyIconModule,
SkyToolbarModule,
TreeModule,
diff --git a/libs/components/angular-tree-component/src/lib/modules/angular-tree/fixtures/tree-view.fixture.component.html b/libs/components/angular-tree-component/src/lib/modules/angular-tree/fixtures/tree-view.fixture.component.html
index f278b1e64b..6e9f41fa58 100644
--- a/libs/components/angular-tree-component/src/lib/modules/angular-tree/fixtures/tree-view.fixture.component.html
+++ b/libs/components/angular-tree-component/src/lib/modules/angular-tree/fixtures/tree-view.fixture.component.html
@@ -18,6 +18,9 @@
#treeNodeFullTemplate
>