projects/i-components/src/lib/components/container/container.component.ts
Angular Component for the container Control.
selector | wm-container |
styleUrls | ./container.component.scss |
Properties |
|
Methods |
Inputs |
Accessors |
constructor(componentFactoryResolver: ComponentFactoryResolver, changeDetectorNotifier: ChangeDectionNotifierService, cd: ChangeDetectorRef, differs: IterableDiffers, viewContainerRef: ViewContainerRef, injectorBase: Injector)
|
|||||||||||||||||||||
Creates an instance of ContainerComponent.
Parameters :
|
controls | |
Type : any
|
|
Set the controls to render. |
addControl | ||||||
addControl(record: any)
|
||||||
Add a new control to the current Angular view
Parameters :
Returns :
void
|
applyChanges | ||||||
applyChanges(changes: any)
|
||||||
This method apply changes when any of the following actions in the model is triggered: forEachRemovedItem: Something has been removed. forEachAddedItem: Something has been added.
Parameters :
Returns :
void
|
detectChangesAction |
detectChangesAction()
|
Handle subscription to the notifyDetectChanges action Refresh the component whenever a model modification was performed
Returns :
void
|
intermediateControl | ||||||
intermediateControl(record: any)
|
||||||
Add an intermediate control if needed.
Parameters :
Returns :
ViewContainerRef
{ViewContainerRef} |
Private markForCheckComp |
markForCheckComp()
|
Marks current component
Returns :
void
|
ngDoCheck |
ngDoCheck()
|
This is part of Angular lifecycle hook. Review the changes in the control's collection and perform the instantiation of the new control's
Returns :
void
|
removeControl | ||||||
removeControl(id: string)
|
||||||
Removes the dynamically opened control
Parameters :
Returns :
void
|
controlsCollection |
Type : any
|
Default value : {}
|
An array of components to render corresponding to the control's that are displayed dynamically |
Private differences |
Type : any
|
The differences that the collection has. |
Protected ngZone |
Type : NgZone
|
Angular´s NgZone accessor |
openedComponents |
Type : any
|
Default value : {}
|
Keeps a reference to the dynamically opened components. |
timeoutChangeDetection |
Type : null
|
Default value : null
|
The timeour change detection |
Public viewContainerRef |
Type : ViewContainerRef
|
Reference to the view containerRef for the component that contains the directive |
controls | ||||||
getcontrols()
|
||||||
Get the controls to render
Returns :
any
|
||||||
setcontrols(value: any)
|
||||||
Set the controls to render.
Parameters :
Returns :
void
|
import {
Component,
ComponentFactoryResolver,
ComponentRef,
DoCheck,
IterableChangeRecord,
IterableDiffers,
Input,
ViewContainerRef,
ChangeDetectorRef,
Optional,
Injector,
NgZone,
} from '@angular/core';
import { UIElement, Guid } from '@mobilize/wms-framework';
import { ChangeDectionNotifierService } from '../../services';
import { Utils } from '../../utils/utilities';
import { CanvasItemComponent } from '../canvas-item/canvas-item.component';
/**
* Angular Component for the container Control.
*
* @export
* @class ContainerComponent
*/
@Component({
selector: 'wm-container',
template: ``,
styleUrls: ['./container.component.scss'],
})
export class ContainerComponent implements DoCheck {
/**
* Reference to the view containerRef for the component that contains the directive
*
* @type {ViewContainerRef}
* @memberof ContainerComponent
*/
public viewContainerRef: ViewContainerRef;
/**
* Keeps a reference to the dynamically
* opened components.
*
* @type {*}
* @memberof ContainerComponent
*/
openedComponents: any = {};
/**
* The timeour change detection
*
* @memberof ContainerComponent
*/
timeoutChangeDetection = null;
/**
* An array of components to render corresponding to the
* control's that are displayed dynamically
*
* @type {any[]}
* @memberof ContainerComponent
*/
controlsCollection: any = {};
/**
* Set the controls to render.
*
* @memberof ContainerComponent
*/
@Input()
set controls(value: any) {
this.controlsCollection = value ?? {};
/* istanbul ignore else */
if (!this.differences && this.differs && value && value.dynamics) {
this.differences = this.differs
.find(this.controlsCollection.dynamics)
.create();
}
}
/**
* Get the controls to render
*
* @readonly
* @type {any[]}
* @memberof ContainerComponent
*/
get controls(): any {
return this.controlsCollection;
}
/**
* The differences that the collection has.
*
* @private
* @type {*}
* @memberof ContainerComponent
*/
private differences: any;
/**
* Angular´s NgZone accessor
*
* @protected
* @type {NgZone}
* @memberof ContainerComponent
*/
protected ngZone: NgZone;
/**
* Creates an instance of ContainerComponent.
*
* @param {ComponentFactoryResolver} componentFactoryResolver
* @memberof ContainerComponent
*/
constructor(
private componentFactoryResolver: ComponentFactoryResolver,
private changeDetectorNotifier: ChangeDectionNotifierService,
private cd: ChangeDetectorRef,
protected differs: IterableDiffers,
viewContainerRef: ViewContainerRef,
@Optional() protected injectorBase: Injector = null
) {
if (this.injectorBase != null) {
this.ngZone = injectorBase.get(NgZone);
}
this.viewContainerRef = viewContainerRef;
}
/**
* This is part of Angular lifecycle hook.
* Review the changes in the control's collection and perform the
* instantiation of the new control's
*
* @memberof ContainerComponent
*/
ngDoCheck(): void {
/* istanbul ignore else */
if (this.differences) {
const changes = this.differences.diff(this.controlsCollection.dynamics);
/* istanbul ignore else */
if (changes) {
this.applyChanges(changes);
}
}
}
/**
* This method apply changes when any of the following actions in the model is triggered:
* forEachRemovedItem: Something has been removed.
* forEachAddedItem: Something has been added.
*
* @param {*} changes
* @memberof ContainerComponent
*/
applyChanges(changes: any): void {
changes.forEachRemovedItem((record: IterableChangeRecord<any>) =>
this.removeControl(record.item['_wmuid'])
);
changes.forEachAddedItem((record: IterableChangeRecord<any>) =>
this.addControl(record)
);
}
/**
* Add a new control to the current Angular view
*
* @param {string} id - id to track the component
* @param {*} componentToLoad - Angular Component to update
* @param {Injector} inject - Angular injector to create the new component
* @memberof ContainerComponent
*/
addControl(record: any): void {
const uid = Guid.newGuid().toString();
record.item['_wmuid'] = uid;
const dynamic = Utils.getUIControls(
[record.item],
this.controlsCollection.injector
)[0];
const viewContainerRef = this.intermediateControl(record);
const componentRef = viewContainerRef.createComponent(dynamic.component, {
index: null,
injector: dynamic.customInjector,
}) as ComponentRef<any>;
if (
['stackpanel', 'tabcontrol', 'wrappanel', 'xamTileMngr'].indexOf(
this.controlsCollection.container
) > -1
) {
this.openedComponents[uid] = componentRef;
}
this.detectChangesAction();
}
/**
* Add an intermediate control if needed.
*
* @param {*} record
* @return {*} {ViewContainerRef}
* @memberof ContainerComponent
*/
intermediateControl(record: any): ViewContainerRef {
let viewContainerRef = this.viewContainerRef;
switch (this.controlsCollection.container) {
case 'canvas': {
let itemIndex: number = undefined;
if (this.controlsCollection.dynamics?.indexOf && record.item) {
itemIndex = this.controlsCollection.dynamics.indexOf(record.item);
itemIndex = itemIndex >= 0 ? itemIndex : undefined;
}
const componentRef = viewContainerRef.createComponent(
CanvasItemComponent,
{ index: itemIndex }
) as ComponentRef<any>;
if (record.item instanceof UIElement) {
componentRef.instance.itemInfo = record.item;
} else {
componentRef.instance.itemInfo = record.item.model;
}
this.openedComponents[record.item['_wmuid']] = componentRef;
viewContainerRef =
componentRef.instance.componentContainer.viewContainerRef;
break;
}
case 'grid': {
break;
}
}
return viewContainerRef;
}
/**
* Removes the dynamically opened control
*
* @param model The control's id unique identifier.
* @memberof ContainerComponent
*/
removeControl(id: string): void {
/* istanbul ignore else */
if (this.openedComponents[id]) {
this.openedComponents[id].destroy();
delete this.openedComponents[id];
}
this.detectChangesAction();
}
/**
* Handle subscription to the notifyDetectChanges action
* Refresh the component whenever a model modification was performed
*
* @memberof ContainerComponent
*/
detectChangesAction(): void {
if (this.ngZone) {
// if ngZone is defined then make sure it executes markforCheck inside Angular´s Zone
this.ngZone?.run(() => {
this.markForCheckComp();
});
} else {
this.markForCheckComp();
}
}
/**
* Marks current component
*
* @private
* @memberof ContainerComponent
*/
private markForCheckComp(): void {
this.cd?.markForCheck();
if (this.changeDetectorNotifier?.timeout) {
clearTimeout(this.changeDetectorNotifier.timeout);
}
if (this.changeDetectorNotifier) {
this.changeDetectorNotifier.timeout = setTimeout(() => {
this.changeDetectorNotifier?.notifyDetectChanges(null);
}, this.changeDetectorNotifier.timer);
}
}
}
./container.component.scss