diff --git a/projects/igniteui-angular-elements/src/app/app.module.ts b/projects/igniteui-angular-elements/src/app/app.module.ts
index 56fa430a99a..1e4c09cc437 100644
--- a/projects/igniteui-angular-elements/src/app/app.module.ts
+++ b/projects/igniteui-angular-elements/src/app/app.module.ts
@@ -31,6 +31,7 @@ import { registerConfig } from "../analyzer/elements.config";
import { createIgxCustomElement } from './create-custom-element';
import { IgxGridStateComponent } from '../lib/state.component';
import { ELEMENTS_TOKEN } from 'igniteui-angular/src/lib/core/utils';
+import { IgxIconBroadcastService } from '../lib/icon.broadcast.service';
@NgModule({
imports: [
@@ -38,13 +39,14 @@ import { ELEMENTS_TOKEN } from 'igniteui-angular/src/lib/core/utils';
BrowserAnimationsModule
],
providers: [
- { provide: ELEMENTS_TOKEN, useValue: true }
+ { provide: ELEMENTS_TOKEN, useValue: true },
+ IgxIconBroadcastService
],
// bootstrap: []
})
export class AppModule {
- constructor(private injector: Injector) {}
+ constructor(private injector: Injector, private _iconBroadcast: IgxIconBroadcastService) {}
ngDoBootstrap() {
diff --git a/projects/igniteui-angular-elements/src/index.html b/projects/igniteui-angular-elements/src/index.html
index 4bd12923148..e1585a6c320 100644
--- a/projects/igniteui-angular-elements/src/index.html
+++ b/projects/igniteui-angular-elements/src/index.html
@@ -73,6 +73,7 @@
Flat Grid (column groups, toolbar, paginator, row
Medium
Large
+
Standalone paginator
@@ -112,10 +113,18 @@ Flat Grid (MRL column layout)
import { html, nothing } from "/lit-html.js";
import { Directive, directive } from "/directive.js";
- import { defineComponents, IgcSelectComponent, IgcComboComponent, IgcButtonComponent, IgcButtonGroupComponent } from "igniteui-webcomponents";
+ import { defineComponents, IgcSelectComponent, IgcComboComponent, IgcButtonComponent, IgcButtonGroupComponent, registerIconFromText, setIconRef } from "igniteui-webcomponents";
// import "igniteui-webcomponents/themes/light/bootstrap.css";
defineComponents(IgcSelectComponent, IgcComboComponent, IgcButtonComponent, IgcButtonGroupComponent);
+
+
+ const buildIcon =
+ '';
+ const thumbUpIcon =
+ '';
+ let icon = thumbUpIcon;
+
const grid1 = document.getElementById('grid1');
const grid2 = document.getElementById('grid2');
const buttonGroup = document.querySelector('igc-button-group');
@@ -196,6 +205,7 @@ Flat Grid (MRL column layout)
document.getElementById("saveState").addEventListener("click", saveState);
document.getElementById("restoreState").addEventListener("click", restoreState);
+ document.getElementById("toggleIcon").addEventListener("click", toggleIcon);
const stateComponent = document.getElementById('state');
stateComponent.options = {
paging: false
@@ -220,6 +230,25 @@ Flat Grid (MRL column layout)
stateComponent.applyState(obj);
}
}
+
+ function toggleIcon() {
+ if (icon !== thumbUpIcon) {
+ icon = thumbUpIcon;
+ registerIconFromText("filter_list", thumbUpIcon, "customSet");
+ setIconRef('filter_list', 'default', {
+ name: 'filter_list',
+ collection: 'customSet',
+ });
+
+ } else {
+ icon = buildIcon;
+ registerIconFromText("filter_list", buildIcon, "customSet2");
+ setIconRef('filter_list', 'default', {
+ name: 'filter_list',
+ collection: 'customSet2',
+ });
+ }
+ }
diff --git a/projects/igniteui-angular-elements/src/lib/icon.broadcast.service.spec.ts b/projects/igniteui-angular-elements/src/lib/icon.broadcast.service.spec.ts
new file mode 100644
index 00000000000..c58d9970e03
--- /dev/null
+++ b/projects/igniteui-angular-elements/src/lib/icon.broadcast.service.spec.ts
@@ -0,0 +1,115 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ActionType, BroadcastIconsChangeMessage, IgxIconBroadcastService, SvgIcon, } from './icon.broadcast.service';
+import { Component, SecurityContext } from '@angular/core';
+import { IconMeta, IgxIconService } from 'igniteui-angular';
+import { wait } from 'igniteui-angular/src/lib/test-utils/ui-interactions.spec';
+
+describe('Icon broadcast service', () => {
+ let fixture: ComponentFixture;
+ let broadcastChannel: BroadcastChannel;
+ let events: BroadcastIconsChangeMessage[] = [];
+ const buildIcon =
+ '';
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [],
+ providers: [IgxIconBroadcastService]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ broadcastChannel = new BroadcastChannel("ignite-ui-icon-channel");
+ broadcastChannel.onmessage = (e: MessageEvent) => {
+ events.push(e.data);
+ }
+ fixture = TestBed.createComponent(BroadcastServiceComponent);
+ });
+
+ afterEach(() => {
+ events = [];
+ broadcastChannel.close();
+ });
+
+ describe('Broadcast Events', () => {
+ it('should correctly process event of icons registering on channel.', async() => {
+ // simulate a new icon being registered on channel
+ const icons: Map> = new Map();
+ const icon: Map = new Map()
+ icon.set("customIcon", { svg: buildIcon });
+ icons.set("customCollection", icon);
+ const message: BroadcastIconsChangeMessage = {
+ actionType: ActionType.RegisterIcon,
+ collections: icons
+ };
+ broadcastChannel.postMessage(message);
+ fixture.detectChanges();
+ await wait(50);
+ fixture.detectChanges();
+ const iconService = fixture.componentInstance.iconService;
+ const svg = iconService.getSvgIcon("customIcon", "customCollection");
+ expect(svg).not.toBeUndefined();
+ });
+
+ it('should correctly process event of setting an icon reference on channel.', async() => {
+ const refs: Map> = new Map();
+ const ref: Map = new Map()
+ ref.set("customIcon", {name: "customIcon", family: "customCollection" });
+ refs.set("customCollection", ref);
+ const message: BroadcastIconsChangeMessage = {
+ actionType: ActionType.RegisterIcon,
+ references: refs
+ };
+ broadcastChannel.postMessage(message);
+ fixture.detectChanges();
+ await wait(50);
+ fixture.detectChanges();
+
+ const iconService = fixture.componentInstance.iconService;
+ const serviceRef = iconService.getIconRef("customIcon", "customCollection");
+ expect(serviceRef.family).toBe("customCollection");
+ expect(serviceRef.name).toBe("customIcon");
+ });
+
+ it('should send a request to sync state from any peer already on the channel on init.', async() => {
+ await wait(50);
+ expect(events.length).toBe(1);
+ expect(events[0].actionType).toBe(ActionType.SyncState);
+ });
+
+ it('should correctly process event of synching full state of icons on channel.', async() => {
+ const icons: Map> = new Map();
+ const icon: Map = new Map()
+ icon.set("customIcon", { svg: buildIcon });
+ icons.set("customCollection", icon);
+ const refs: Map> = new Map();
+ const ref: Map = new Map()
+ ref.set("customIcon", {name: "customIcon", family: "customCollection" });
+ refs.set("customCollection", ref);
+ const message: BroadcastIconsChangeMessage = {
+ actionType: ActionType.SyncState,
+ collections: icons,
+ references: refs
+ };
+ broadcastChannel.postMessage(message);
+ await wait(50);
+ const iconService = fixture.componentInstance.iconService;
+ const svg = iconService.getSvgIcon("customIcon", "customCollection");
+ expect(svg).not.toBeUndefined();
+ const serviceRef = iconService.getIconRef("customIcon", "customCollection");
+ expect(serviceRef.family).toBe("customCollection");
+ expect(serviceRef.name).toBe("customIcon");
+ });
+ })
+});
+
+@Component({
+ template: `
+ `,
+ standalone: true,
+ providers: [IgxIconBroadcastService, IgxIconService]
+})
+export class BroadcastServiceComponent {
+ constructor(public iconBroadcast: IgxIconBroadcastService, public iconService: IgxIconService) {}
+}
diff --git a/projects/igniteui-angular-elements/src/lib/icon.broadcast.service.ts b/projects/igniteui-angular-elements/src/lib/icon.broadcast.service.ts
new file mode 100644
index 00000000000..34a32a8c4d6
--- /dev/null
+++ b/projects/igniteui-angular-elements/src/lib/icon.broadcast.service.ts
@@ -0,0 +1,82 @@
+import { Injectable, Optional } from '@angular/core';
+import { PlatformUtil } from '../../../igniteui-angular/src/lib/core/utils';
+import { IconMeta, IgxIconService } from '../../../igniteui-angular/src/lib/icon/icon.service';
+
+
+export interface SvgIcon {
+ svg: string;
+ title?: string;
+ }
+
+ export type Collection = Map;
+
+ export enum ActionType {
+ SyncState = 0,
+ RegisterIcon = 1,
+ UpdateIconReference = 2,
+ }
+
+ export interface BroadcastIconsChangeMessage {
+ actionType: ActionType;
+ collections?: Collection>;
+ references?: Collection>;
+ }
+
+/** @hidden @internal **/
+@Injectable()
+export class IgxIconBroadcastService {
+ private iconBroadcastChannel: BroadcastChannel;
+ constructor(
+ protected _iconService: IgxIconService,
+ @Optional() private _platformUtil: PlatformUtil
+ ) {
+ if (this._platformUtil?.isBrowser) {
+ // open broadcast channel for sync with wc icon service.
+ this.iconBroadcastChannel = new BroadcastChannel("ignite-ui-icon-channel");
+ this.iconBroadcastChannel.onmessage = (event) => {
+ const message = event.data as BroadcastIconsChangeMessage;
+ if (message.actionType === ActionType.SyncState ||
+ message.actionType === ActionType.RegisterIcon) {
+ this.updateIconsFromCollection(message.collections);
+ }
+
+ if (message.actionType === ActionType.SyncState ||
+ message.actionType === ActionType.UpdateIconReference) {
+ this.updateRefsFromCollection(message.references);
+ }
+ };
+ // send message to sync state
+ this.iconBroadcastChannel.postMessage({
+ actionType: ActionType.SyncState
+ });
+ }
+ }
+
+ private updateIconsFromCollection(collections: Collection>) {
+ if (!collections) return;
+ const collectionKeys = collections.keys();
+ for (const collectionKey of collectionKeys) {
+ const collection = collections.get(collectionKey);
+ for (const iconKey of collection.keys()) {
+ const value = collection.get(iconKey).svg;
+ this._iconService.addSvgIconFromText(iconKey, value, collectionKey);
+ }
+ }
+ }
+
+ private updateRefsFromCollection(collections: Collection>) {
+ if (!collections) return;
+ const collectionKeys = collections.keys();
+ for (const collectionKey of collectionKeys) {
+ const collection = collections.get(collectionKey);
+ for (const iconKey of collection.keys()) {
+ const collectionName = collection.get(iconKey).collection;
+ this._iconService.setIconRef(iconKey, 'default', {
+ family: collectionName,
+ name: iconKey
+ });
+ }
+ }
+ }
+
+}